Sondaki yeni satır karakteri komut yerine koymamdan nereye gitti?


15

Aşağıdaki kod durumu en iyi açıklar. Son satır neden sondaki yeni satır karakterini vermiyor? Her satırın çıktısı yorumda gösterilir. Ben kullanıyorum GNU bash, sürüm 4.1.5

     echo -n $'a\nb\n'                  | xxd -p  # 610a620a  
           x=$'a\nb\n'   ; echo -n "$x" | xxd -p  # 610a620a
     echo -ne "a\nb\n"                  | xxd -p  # 610a620a
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p  # 610a62

4
İhtiyaç duyulduğunda nadir zamanlar için geçici çözüm:tmp=$(somecommand; echo a); tmp=${tmp%a}
Gilles 'SO- kötü olmayı bırak'


1
@Gilles: Örneğiniz, yukarıdaki örnek: tmp=$(somecommand; echo a)... Bu kesinlikle noktayı eve götürdü ... Örneği görene kadar, tenhalığım hala kullanmak olurdu echo -n a... ama, elbette!, Gerek yok -nçünkü Komut değişikliği her durumda tanıtılan sondaki yeni satır kaldırır! ... Teşekkürler...
Peter.O

Yanıtlar:


18

Komut ikame işlevi $()(ve kuzeni backtick) özellikle arkadaki satırları kaldırır. Bu, belgelenmiş davranıştır ve yapıyı kullanırken her zaman bunun farkında olmalısınız.

Metin gövdesindeki yeni satırlar, ikame operatörü tarafından kaldırılmaz, ancak kabuk üzerinde sözcük ayırma işlemi sırasında da kaldırılabilir; Bu iki kullanım arasındaki farka dikkat edin:

$ echo -n "$(echo -n 'a\nb')"
a
b

$ !! | xxd -p
610a62

$ echo -n  $(echo -n 'a\nb')
a b

$ !! | xxd -p   
612062

İkinci örnekte, çıktıdan alıntı yapılmadı ve yeni satır, sözcük ayrımı olarak yorumlandı ve çıktıda boşluk olarak gösterildi!


1
Teşekkür Caleb .. Ben ne zaman tek bir alana boşluk değişen kelime bölünme farkında tırnaksız ... Ben alıntı sanki Ben en çok benim sondaki yeni satır bile yok olmasını görmek şaşırdı nedeni budur ... Şimdi farkındayım çünkü Komuta Yerine Koyma 'normal' davranışını takip eden bir yeni satır bırakıyor ... Ah, en la vie .. ve bağlantı için teşekkürler
Peter.O

6

Komut ikamesi kullanılırken, kabuk komutları alt kabukta yürütür ve stdout'larını döndürür. bu süreçte, övgü düz bölünmüş sözcükler döndürdüğü için IFS karakterleri önemlerini kaybeder (tırnak işareti yoksa), böylece sondaki karakterler kaldırılır. Örneğin:

$ echo "$(echo -e '\n')" | wc
 1       0       1

$ echo -e '\n' | wc
2       0       2

ve daha pratik olarak, pwddizin adınız arasında yeni bir satır olsa bile çalışır, ancak çalışmayacaktır $(pwd).

Genel çözüm, komutunuzun sonuna bir şey eklemek ve daha sonra onu kaldırmaktır.


1
Eğer örnekler mantıklı için teşekkürler Philomath ... bu arada, ilk örnek sözdizimsel yanlıştır .. ( 'wc' an arg bir dize kabul etmez), ilki olabilir echo "$(echo -e '\n')" | wc, hangi çıkışlar 1   0   1ile karşılaştırıldığında,2   0   2
Peter.O

@fred: Hata! Sadece bir yazım hatası.
Philomath

1
"mekanlara dönüştürülmüş" uygun bir açıklama değildir, sadece bazı bölünmeler söz konusudur. Özellikle IFS'den alan kaldırabilirsiniz ve bunlar ayırıcılar olarak çalışmaz. Daha fazla, senin örneğin özel bir durum kategoriye girmektedir ve arasında bir fark yoktur $(pwd)ve "$(pwd)", Caleb'in cevaba bakınız.
Stéphane Gimenez

Not: Her zamanki çözüm önerisi, bunu temizlemek için ihtiyacım olan şey.
Peter.O

Yeniden "boşluklara dönüştürüldü", bkz. Word Splitting
Peter.O
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.