Gelen bu soru birisi bir kullanırken sorun raporları burada belgeyi içinde bir alıntı sınırlayıcı kelime ile $(...)
komut ikamesi bir ters eğik çizgi, \
belge tetikleyiciler içinde bir satırın sonundaki newline-birleştiren çizgi devamında , burada aynı süre belgelemek dışında beklendiği gibi komut ikamesi işleri .
İşte basitleştirilmiş bir örnek belge:
cat <<'EOT'
abc ` def
ghi \
jkl
EOT
Bu, bir satırın sonunda bir ters tırnak ve bir ters eğik çizgi içerir. Sınırlayıcı belirtilir, bu nedenle vücudun içinde herhangi bir genişleme meydana gelmez. Tüm Bourne-aliklerinde bu çıktıları kelimesi kelimesine bulabilirim. Aynı belgeyi aşağıdaki gibi bir komut yerine koyarsam:
x=$(cat <<'EOT'
abc ` def
ghi \
jkl
EOT
)
echo "$x"
artık aynı şekilde davranmazlar:
dash
,ash
,zsh
,ksh93
, BusyBoxash
,mksh
ve SunOS 5.10 POSIXsh
hepsi daha önce olduğu gibi dökümanının birebir içeriğini verir.- Bash 3.2, benzersiz bir backtick için bir sözdizimi hatası verir. Eşleştirilen ters tırnaklarla, içeriği bir komut olarak çalıştırmaya çalışır.
- Bash 4.3, "ghi" ve "jkl" değerlerini tek bir satıra daraltır, ancak hata içermez.
--posix
Seçenek bu etkilemez. Kusalananda banapdksh
aynı şekilde davrandığını söylüyor (teşekkürler!) .
Orijinal soruda, bunun Bash ayrıştırıcısında bir hata olduğunu söyledim. Bu mu? [Güncelleme: evet ] Bulabileceğim POSIX'ten (tümü Kabuk Komut Dili tanımından) ilgili metin:
- §2.6.3 Komut Değiştirme :
$ (Komut) formuyla, eşleşen kapanış parantezine açık parantezin ardından gelen tüm karakterler komutu oluşturur. Herhangi geçerli kabuk komut dosyası için kullanılabilir komutu yalnızca belirtilmemiş sonuçlar üretir yönlendirmeler oluşan bir senaryo dışında.
- §2.7.4 Burada-Belge :
Herhangi bir bölümü ise kelimenin alıntı, ayırıcı üzerindeki alıntı çıkarılmasını gerçekleştirerek kurulacaktır kelime ve burada-belge satırları, genişletilmiş edilmeyecektir.
- §2.2.1 Kaçış Karakteri (Ters Eğik Çizgi) :
<newline> <ters eğik çizgiyi> takip ederse, kabuk bunu satır devamı olarak yorumlayacaktır. Giriş, belirteçlere bölünmeden önce <ters eğik çizgi> ve <yeni satır> kaldırılacaktır.
- §2.3 Jeton Tanıma :
Bir io_here belirteci dilbilgisi tarafından tanındığında (bkz. Kabuk Dilbilgisi ), bir sonraki NEWLINE belirtecinin hemen ardından gelen bir veya daha fazla satır , bir veya daha fazla burada bulunan belgenin gövdesini oluşturur ve Here- kurallarına göre ayrıştırılır. Belge .
Bir io_burayı işlemediğinde , kabuk, girişindeki bir sonraki karaktere aşağıdaki ilk uygulanabilir kuralı uygulayarak girdisini belirteçlere bölmelidir . ...
...
- Geçerli karakter <ters eğik çizgi>, tek tırnak veya çift tırnak işareti içeriyorsa ve tırnak içine alınmamışsa, tırnak içine alınan metnin sonuna kadar sonraki karakterler için tırnak işaretini etkiler. Alıntı için kurallar açıklanmaktadır teklif . Jeton tanıma sırasında hiçbir ikame gerçekleştirilmeyecek ve sonuç belirteci, girişte görünen (<newline> katılma hariç), değiştirilmemiş, gömülü veya ekli tırnak işaretleri veya ikame operatörleri dahil olmak üzere, ve son arasındaki karakterleri içermelidir. alıntılanan metnin.
Benim yorumum $(
, sonlandırmaya kadar olan tüm karakterlerin )
kabuk betiğini, kelimesi kelimesine; burada belge görünür, bu nedenle sıradan belirleme yerine burada belge işleme gerçekleşir; buradaki belgenin alıntılanmış bir sınırlayıcısı vardır, yani içeriği kelimesi kelimesine işlenir; ve kaçış karakteri asla içine girmez. Ancak bu durumun ele alınmadığına ve her iki davranışa da izin verildiğine dair bir argüman görebiliyorum. Bir yerde de alakalı metnin bazılarını atlamış olabilirim.
- Bu durum başka yerlerde daha açık hale getirildi mi?
- Taşınabilir bir script neye güvenebilmelidir (teoride)?
- Bu kabuklardan herhangi birinin (Bash 3.2 / Bash 4.3 / diğer herkes) verdiği özel tedavi standart tarafından zorunlu mu? Yasak? İzin verilen?
echo "$x"
, ancak değişken çalışmalarını incelemek için herhangi bir yol. O satırı dibine düzenledim.
$(...)
bu çıktı ne olursa olsun onun yerine geçer ... Şimdi, örneğin bir alt kabukta (in bash
) komutu çalıştırdığınızda beklenen sonucu verir. Yalnızca komut yerine koymaya dönüştürüldüğünde "ghi" ve "jkl" kelimelerini daraltır. Yani bu bir böcek imo