Bash backtick operatörünün yeni satırları çıktıda tutmasını nasıl sağlayabilirim?


36

Bastonun backtick yerine yenisini yememesini sağlamanın bir yolu var mı?

Örneğin:

var=`echo line one && echo line two`
echo $var

line one line two

İstediğim şey

var=`echo line one && echo line two` # plus some magic
echo $var

line one
line two

Yanıtlar:


54

Bu, backticks oyuncu değişikliği ile ilgili bir sorun değil echo; Kontrol karakterlerinin çalışabilmesi için değişkene fiyat vermelisiniz:

$ var=`echo line one && echo line two`
$ echo "$var"
line one
line two

Yani bash komut satırındaki değişkenleri genişletirken yeni satırları kaldırır. Ve bu davranış değişkenden alıntı yaparak etkisizleştirilebilir mi?
saat

7
bashalıntı, bir komut çalıştırmadan önce gerçekleştirir parametreleri genişleme bilgilendirmek gerekir bashtek bir dize değil, 4 kelime yazdırmak istediğiniz ( line, one, lineve two). Deneyin: echo a <many spaces> bve echo "a <many spaces> b". Bu cevaba da bir göz atın .
cYrus 23:12

5

@Cyrus doğru olsa bile - aslında tüm soruyu yanıtlamıyor ve ne olduğuna dair bir açıklama yok.

Öyleyse içinden geçelim.

Dize Newlines

İlk önce beklenen bayt sırasını belirleyin:

$ { echo a; echo b; } | xxd
0000000: 610a 620a                                a.b.

Şimdi, bu bayt sırasını yakalamaya çalışmak için Komut Değiştirme (Bölüm 3.5.4) kullanın:

$ x=$( echo a; echo b; )

Ardından, bayt sırasını doğrulamak için basit bir yankı yapın:

$ echo $x | xxd
0000000: 6120 620a                                a b.

Öyle görünüyor ki ilk satırsonu boşlukla değiştirildi ve ikinci satırsonu bozulmadan kaldı. Ama neden ?

Burada gerçekten neler olduğuna bir bakalım:

İlk önce, bash Shell Parametre Expansion'ı (Bölüm 3.5.3) yapacak

'$' Karakteri, parametre genişletme, komut değiştirme veya aritmetik genişletme işlevini sunar. Genişletilecek olan parametre adı veya simge isteğe bağlı olan ancak adın bir parçası olarak yorumlanabilecek karakterden hemen sonra genişleyen değişkenlerden korunmak için hizmet veren parantez içine alınabilir.

Ardından bash, Word Bölme (Bölüm 3.5.7) yapacak

Kabuk, sözcük bölme için çift tırnak içinde oluşmayan parametre genişletme, komut değiştirme ve aritmetik genişletme sonuçlarını tarar.

Kabuk, $ IFS'in her karakterini sınırlayıcı olarak kabul eder ve diğer genişlemelerin sonuçlarını bu karakterler üzerindeki kelimelere böler. IFS ayarlanmamışsa veya değeri tam olarak ...

Daha sonra, bash basit bir komut olarak görecektir (Kısım 3.2.1)

Basit bir komut, en sık karşılaşılan komut türüdür. Bu sadece kabuğun kontrol operatörlerinden biri tarafından sonlandırılan, boşluklarla ayrılmış bir sözcük dizisidir (bkz. Tanımlar). İlk kelime genellikle yürütülecek bir komutu belirtir, kelimelerin geri kalanı o komutun argümanlarıdır.

Boşlukların tanımı (Bölüm 2 - Tanımlar)

blank Bir boşluk veya sekme karakteri.

Son olarak, bash yankı çağırır (Bölüm 4.2 - Bash Builtin Commands) iç komut

... Boşluklarla ayrılmış, yeni bir satırla sonlandırılan arıları çıktı. ...

Özetlemek gerekirse, yeni satırlar Word Bölme ile kaldırılır ve daha sonra eko 2 argümanı "a" ve "b" alır ve sonra onları boşluklarla ayırıp yeni bir satır ile biter.

@Cyrus’un önerdiği şeyi yapmak (ve newline 'ı ecn'den bastırmak) sonucu daha iyidir:

$ echo -n "$x" | xxd
0000000: 610a 62                                  a.b

Dizenin sonundaki Newlines

Yine de mükemmel değil, izleyen newline gitti. Komuta Değiştirme’ne daha yakından bakmak (Kısım 3.5.4) :

Bash, komutu yürüterek ve komut yerine kullanılanı komutun standart çıktısıyla değiştirilerek izleyen yeni satırlar silinir.

Artık yeni hattın neden ortadan kalktığı belli olduğu için, bash onu tutmaya kandırılabilir. Bunu yapmak için, sonuna ek bir dize ekleyin ve değişkeni kullanırken onu kaldırın:

$ x=$( echo a; echo b; echo -n extra )
$ echo -n "${x%extra}" | xxd
0000000: 610a 620a                                a.b.

TL; DR

Çıktının sonuna fazladan bölüm ekleyin ve değişkenleri alıntılayın:

$ cat /no/file/here 2>&1 | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865  cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65  re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a        or directory.
$ cat /no/file/here 2>&1 | cksum
3561909523 46
$ 
$ var=$( cat /no/file/here 2>&1; rc=${?}; echo extra; exit ${rc})
$ echo $?
1
$ 
$ echo -n "${var%extra}" | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865  cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65  re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a        or directory.
$ echo -n "${var%extra}" | cksum
3561909523 46

0

Küçük ilacımı CYrus'un cevabı üzerine yapılan bir yorumuma eklerdim, ancak sanırım cevapları yorumlayamıyorum. Bu yüzden cYrus’un parçasını eksiksiz olma cevabını çoğaltacağım.

Kodunuzun ilk satırında olan şey, gerçekte backticks ikamesinin, yerine konulan komutun çıktısının izleyen yeni satırlarını belgelendiği gibi yiyor olmasıdır . Ancak iki satırınız arasındaki yeni çizgiyi yemez.

İkinci kod satırında olan yankı, birinci ve ikinci satır olmak üzere iki argümanla yürütülmesidir. Genişletilmiş değişkenden alıntı yapmak şunları düzeltir: echo "$var"Bu, birinci satırınız ve ikinci satırınız arasındaki yeni satırı koruyacaktır. Ve echoher şeyin yolunda gitmesi için varsayılan olarak izleyen bir yeni satır ekleyeceğiz.

Şimdi, izleyen tüm yeni satırları bir komut değişikliğinin çıktısındaki korumak istiyorsanız, bir çözüm, komut değiştirme işleminden sonra çıkarabileceğiniz çıktının başka bir satır eklenmesidir, buraya bakınız .

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.