Bas değişkenlerinde yeni satır


9

Bir bash değişkeninde birden çok satır depolamaya çalışıyorum, ancak işe yaramıyor gibi görünüyor.

Örneğin, /binher satırda bir dosya listeler ve depolarsam $LS, $LSstdin olarak iletirseniz wc, her zaman 1 döndürür:

$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1

Ekrana çıktı almaya çalışırsam, çeşitli sonuçlar elde ederim: echotüm satırları tek bir satıra printfyazdırırken, yalnızca ilk satırı yazdırır:

#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS

Peki, bir bash değişkeni birden fazla satır içerebilir mi?

Yanıtlar:


15

İki kez alıntı yapmanız gerekir (ve çoğu durumda değişkenleri iki kez alıntılamanız gerekir ):

echo "$LS"

Ancak bunun yerine printf kullanarak değişken içeriğini yazdırmak için echo kullanmayın :

printf '%s\n' "$LS"

1
Sadece genel cevaba daha iyi bir nokta koymak için: printf bir format dizesinin ilk parametresi olmasını bekler, bu yüzden beklediklerini görmediler. Çıktıda printf'den satırsonu görmek istiyorlarsa, keyfi olarak boşluklara bölünürlerdi printf "%s\n" $LS.
Jeff Schaller

% LS $ LS, btw olmalıdır (Bu kadar kısa bir düzenleme yapamadım)
Jeff Schaller

Teşekkürler! Tabii ki wcve diğer komutlarla da çalışır :wc -l <<< "$LS"
Wizard79

1
@JeffSchaller: Hayır, bu durumda değişkeni ayırmamalısınız, sadece printf '%s\n' "$LS"satırsonu görmek istiyorsanız kullanın. Bu yanlış yazılmış, düzeltildi!
cuonglm

Değişkenleri yazdırmak için neden echo kullanmamalısınız?
123

9

Yeni satırlar değişkendir. LS=$(ls -1)değişkeni LSçıkışa ayarlar ls -1(bu lsarada, çıkış bir terminale gittiği zamankiyle aynı çıktıyı üretir ) eksi sondaki yeni satırlar.

Sorun, değeri yazdırdığınızda yeni satırları kaldırmanızdır. Bir kabuk komut dosyasında $LS“değişkenin değeri” anlamına gelmez, “değerini LSalmak, LSkelimelere göre kelimelere ayırmak IFSve her kelimeyi bir glob paterni olarak yorumlamak” anlamına gelir. Değerini elde etmek LSiçin yazmanız "$LS"veya daha genel olarak $LSçift ​​tırnak arasına koymanız gerekir .

echo "$LS"LSters eğik çizgi karakterlerini yorumlayan bazı kabuklar dışında ve ile başlayan birkaç değer dışında değerini yazdırır -.

printf "$LS"LSyüzde veya ters eğik çizgi karakteri içermediği ve (çoğu uygulamada) ile başlamadığı sürece değerini yazdırır -.

Değerini LStam olarak yazdırmak için düğmesini kullanın printf %s "$LS". Sonunda yeni satır istiyorsanız, kullanın printf '%s\n' "$LS".

$(ls)Genel olarak geçerli dizindeki dosyaların listesi olmadığını unutmayın . Bu yalnızca dosya adlarını yeterince evcilleştirdiğinizde çalışır. (Nokta dosyalar hariç) dosya adlarının listesini almak için, bir joker kullanmak gerekir: *. Sonuç, bir dize değil, bir dize listesidir, bu nedenle bir dize değişkenine atayamazsınız; files=(*)bunları destekleyen kabuklarda bir dizi değişkeni kullanabilirsiniz (ksh93, bash, zsh).

Daha fazla bilgi için bkz. Kabuk betiğim neden boşlukta veya diğer özel karakterlerde boğuluyor?


printf "$ LS", yankı benzeri karakter ayrıştırma işlemine ters
düşebilir

0

Adı geçen

printf '%s\n' "$LS"

tek doğru çözümdür.

Beni diğer önerilen çözümler, hem göstermek edelim echove printfsadece düzgün çalışmaz:

$ mkdir t
$ cd t
$ touch \\n
$ LS=$(ls -l)
$ echo "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf "$LS\n"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf '%s\n' "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ ls -l
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ rm \\n
$ cd ..
$ rmdir t
$

(Bir de V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"ve varyasyonları ile test edebilirsiniz .)

Oysa \nDosya adlarında bu ortak, mağaza olmayabilir git diffbir değişkene ve literal karşılaşma şansınız \ndramatik artış.


Not kshve zshayrıca destek print -r -- "$LS"ve zshde vardır echo -E - $LS. cshsahip echo $LS:q$ LS boş ve ilk etapta $ LS içine satırlı değer elde csh'ın oldukça zor olması durumunda değil çıkış satır karakteri yok ama.
Stéphane Chazelas
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.