Bir bash dizi değişkenini newlines ile ayrılmış bir dizeye nasıl dönüştürebilirim?


50

Her eleman yeni bir satırda bir bash dizi değişkeni bir dosyaya yazmak istiyorum. Bunu for döngüsü ile yapabilirdim, fakat elementleri birleştirmenin başka (temizleyici) bir yolu var \nmı?

Yanıtlar:


59

İşte bash parametresi genişlemesini ve IFSözel değişkenini kullanan bir yöntem .

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

IFSGeçerli ortamdaki değerin üzerine yazmaktan kaçınmak için bir alt kabuk kullanıyoruz . Bu alt kabukta, IFSilk karakterin yeni bir satır olması için ( $'...'tırnak işareti kullanarak ) değerini değiştiririz . Son olarak, dizinin içeriğini tek bir sözcük olarak yazdırmak için parametre genişletmeyi kullanırız; her eleman ilk karakteriyle ayrılır IFS.

Bir değişkeni yakalamak için:

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

Eğer bash'iniz yeterince yeniyse (4.2 veya üstü), seçenekle printfbirlikte hala kullanabilirsiniz (ve gerekir) -v:

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

Her iki durumda da, son satırın içinde olmasını istemeyebilirsiniz var. Kaldırmak için:

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

Teşekkürler, bunu bir değişkene vermenin bir yolu var mı?
ACyclic

Bir değişkene nasıl yakalanacağını göstermek için güncellendi.
chepner

2
Bunun var=${var%?}yerine son örnek olmamalı mı? Bu normal bir ifade değildir, bu nedenle .sadece bir dönem karakteriyle eşleşir.
musiphil

Dizi değişkeni adı tırnaklarını gerekir:$ IFS=', ' $ echo ${VAR[*]} first second third $ echo "${VAR[*]}" first,second,third
Seff

28

printfHer bir dizi öğesini kendi satırında yazdırmak için kullanabilirsiniz :

 $ 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[@]}"

veya

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

veya

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

veya

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

veya

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

veya

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

veya

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

veya

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

Şimdiye kadar hatırlatabildiğim tek şey bu.


2

Yukarıdaki çözümler hemen hemen aynı, ancak orijinal soru çıktının dosyaya çıkmasını istiyor:

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

Notlar: 1) 'echo' son satırın sonunu verir 2) Eğer bu dosya tekrar bash tarafından okunacaksa, -p 'nin istenen serileştirme olabileceğini beyan edin.


2

Kullanımı için :

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

Kullanımı tarihini ; değerleriniz içeriyorsa bunun başarısız olacağını unutmayın !:

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

Kullanımı basename ; değerleriniz içeriyorsa bunun başarısız olacağını unutmayın /:

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

Kullanımı SHUF ; sonuçların sırayla ortaya çıkmayabileceğini unutmayın:

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

0

Benim alabilir mutasyona olmadan sadece Bash yerleşiklerini kullanarak IFS:

# $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}}"
}

Örnek

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

Herhangi bir ayırıcı da kullanabilirsiniz:

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

-1

printf Bir diziden ayrılmış bir dize oluşturmak için en etkili yaklaşım gibi görünüyor:

# 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

Bunu yapmanın daha basit bir yolu:

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

Örnek

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

2
Downvoter, lütfen burada neyin yanlış olduğunu yorumlayın.
kodlayıcı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.