bash 배열 변수를 줄 바꿈으로 구분 된 문자열로 어떻게 변환합니까?


50

bash 배열 변수를 파일에 쓰고 각 요소를 새 줄에 작성하고 싶습니다. for 루프 로이 작업을 수행 할 수 있지만 요소를 결합하는 또 다른 (깨끗한) 방법이 \n있습니까?

답변:


59

bash 매개 변수 확장 및 IFS특수 변수 를 활용하는 방법은 다음과 같습니다 .

$ System=('s1' 's2' 's3' 's4 4 4')
$ ( IFS=$'\n'; echo "${System[*]}" )

IFS현재 환경에서 값을 덮어 쓰지 않도록 서브 쉘을 사용 합니다. 그 서브 쉘에서 우리 IFS는 첫 번째 문자가 개행 ( $'...'따옴표 사용 ) 이되도록 값을 수정합니다 . 마지막으로, 매개 변수 확장을 사용하여 배열의 내용을 단일 단어로 인쇄합니다. 각 요소는의 첫 번째 문자로 구분됩니다 IFS.

변수를 캡처하려면 :

$ var=$( IFS=$'\n'; echo "${System[*]}" )

bash가 충분히 새롭다면 (4.2 이상) printf다음 -v옵션으로 계속 사용할 수 있습니다.

$ printf -v var "%s\n" "${System[@]}"

두 경우 모두에서 개행 문자를 원하지 않을 수 있습니다 var. 그것을 제거하려면 :

$ var=${var%?}    # Remove the final character of var

고맙습니다, 이것을 변수로 출력하는 방법이 있습니까?
ACyclic

변수를 캡처하는 방법을 보여주기 위해 업데이트되었습니다.
chepner

2
마지막 예가 var=${var%?}대신 해서는 안 됩니까? 이것은 정규식이 아니므 .로 마침표 만 일치합니다.
musiphil

배열 변수 이름을 인용해야합니다.$ IFS=', ' $ echo ${VAR[*]} first second third $ echo "${VAR[*]}" first,second,third
Seff

28

printf각 배열 항목을 자체 행에 인쇄 하는 데 사용할 수 있습니다 .

 $ System=('s1' 's2' 's3' 's4 4 4')
 $ printf "%s\n"  "${System[@]}"
s1
s2
s3
s4 4 4

7
awk -v sep='\n' 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"

또는

perl -le 'print join "\n",@ARGV' "${arr[@]}"

또는

python -c 'import sys;print "\n".join(sys.argv[1:])' "${arr[@]}"

또는

sh -c 'IFS=$'\''\n'\'';echo "$*"' '' "${arr[@]}"

또는

lua <(echo 'print(table.concat(arg,"\n"))') "${arr[@]}"

또는

tclsh <(echo 'puts [join $argv "\n"]') "${arr[@]}"

또는

php -r 'echo implode("\n",array_slice($argv,1));' -- "${arr[@]}"

또는

ruby -e 'puts ARGV.join("\n")' "${arr[@]}"

그것이 내가 지금까지 상기시킬 수있는 전부입니다.


2

위의 솔루션은 거의 비슷하지만 원래 질문은 파일로 출력을 요청합니다.

$ a=(a b c d e)
$ ( IFS=$'\n'; echo "${a[*]}" ) > /tmp/file
$ cat /tmp/file
a
b
c
d
e
$

참고 : 1) 'echo'는 마지막 줄 바꿈을 제공합니다. 2)이 파일을 bash에서 다시 읽은 경우 선언 -p가 직렬화가 필요할 수 있습니다.


2

사용 을 위해 :

for each in "${alpha[@]}"
do
  echo "$each"
done

역사 사용하기 ; 값에 다음이 포함되어 있으면 실패합니다 !.

history -p "${alpha[@]}"

basename 사용 ; 값에 다음이 포함되어 있으면 실패합니다 /.

basename -a "${alpha[@]}"

shuf 사용 ; 결과가 순서대로 나오지 않을 수 있습니다.

shuf -e "${alpha[@]}"

0

변경하지 않고 Bash 내장 만 사용하는 내 takeIFS :

# $1  separator
# $2… strings
join_strings () {
    declare separator="$1";
    declare -a args=("${@:2}");
    declare result;
    printf -v result '%s' "${args[@]/#/$separator}";
    printf '%s' "${result:${#separator}}"
}

$ join_strings $'\n' "a b c" "d e f" "g h i"
a b c
d e f
g h i

모든 구분 기호를 사용할 수도 있습니다.

$ join_strings '===' "a b c" "d e f" "g h i"
a b c===d e f===g h i

-1

printf 배열에서 구분 된 문자열을 만드는 가장 효율적인 방법 인 것 같습니다.

# create a delimited string; note that printf doesn't put the trailing delimiter
# need to save and restore IFS
# it is prudent to put the whole logic on a single line so as to minimize the risk of future code changes breaking the sequence of saving/restoring of IFS
oldIFS=$IFS; IFS=$'\n'; printf -v var "${arr[*]}"; IFS=$oldIFS

# print string to file; note that the newline is required in the format string because printf wouldn't put a trailing delimiter (which is a good thing)
printf '%s\n' "$var" > file

이를 수행하는 가장 간단한 방법은 다음과 같습니다.

delim=$'\n'
printf -v var "%s$delim" "${arr[@]}" # create a delimited string
var="${var%$delim}"                  # remove the trailing delimiter

delim=:
arr=(one two three)
printf -v var "%s$delim" "${arr[@]}" # yields one:two:three:
var="${var%$delim}"                  # yields one:two_three

2
Downvoter, 여기에 무엇이 잘못되었는지 언급하십시오.
codeforester 2018 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.