POSIX kabuğu: `$` bir sözcükteki son karakterse özel anlamını kaybediyor mu?


17

Kül, çizgi ve bash üzerinde koştuğumda

$ echo ab$

geri döner

ab$

Bu davranış POSIX tarafından belirtilmiş mi, yoksa POSIX uyumlu kabuklarda ortak bir kural mı? POSIX Kabuk Komut Dili sayfasında bu davranıştan bahseden hiçbir şey bulamadım.


4
Daha iyi olan soru " Eğer bir kelimenin son karakteri ise özel bir anlam $ kazanıyor mu ?" Tek bir özel anlamı yoktur $; parametre genişletme ${...}, komut ikamesi $(...)ve aritmetik ifadeler gibi birden çok, ancak farklı genişletme yapmak için kullanılır $((...)). Bazı mermiler, kshkomutun yerine koyma varyantı gibi ek bağlamlar x=${ echo foo; echo bar;}getirir (bu $(...), bir alt kabukta komutları yerine getirmeyerek standarttan farklıdır ).
chepner

@chepner Issac ve Michael Homer arasındaki fikir farkını tartmak ister misiniz? Cevapları açıkça birbiriyle çelişiyor
Harold Fischer

1
Michael Homer'in yorumuna katılıyorum; kabuk ayrıştırma tamamlanıncaya kadar açılımlar hakkında endişelenmeye bile başlamaz, bu nedenle tek kelimede ab$, $orijinal giriş dizesindeki boş bir karakterle veya bir kutudaki boşlukla "ardından" devam edip etmediğini izleyen hiçbir karakter yoktur. gibi echo ab$ foo; orijinal tırnaksız boşluk ayrıştırıldıktan sonra tanındı ve atıldı.
chepner

Yanıtlar:


10

$tek başına özel bir anlamı yoktur (deneyin echo $), ancak ondan sonra başka bir karakterle birleştirildiğinde ve bir genişleme oluşturulduğunda, örneğin $var(veya ${var}) $(util),, $((1+2)).

$Bölümünde POSIX standardında bir genişleme tanımlayan olarak anlam onun "special" alır Jeton Tanıma :

Geçerli karakter sıralanmamışsa $veya `kabuk, başlangıçtaki sıralanmamış karakter dizilerinden sırasıyla parametre genişletme, komut ikamesi veya aritmetik genişletme için adayların başlangıcını tanımlamalıdır: $veya ${, $(veya `, ve $((. Kabuk, genişletilecek birimin ucunu belirlemek için yeterli girişi okumalıdır ( belirtilen bölümlerde açıklandığı gibi)). Karakterler işlenirken, genişletme veya alıntılama örnekleri ikame içinde yuvalanmış bulunursa, kabuk, bulunan yapı için belirtilen şekilde bunları özyinelemeli olarak işleyecektir. Yer değiştirmenin başlangıcından sonuna kadar bulunan ve gömülü yapıları tanımak için gereken herhangi bir özyinelemeye izin veren karakterler, gömülü veya ek ikame operatörleri veya tırnakları dahil olmak üzere sonuç belirtecine değiştirilmeden dahil edilir. Jeton, oyuncu değişikliği sonunda sınırlandırılmayacaktır.

Dolayısıyla, $bir genişleme oluşturmazsa, diğer ayrıştırma kuralları yürürlüğe girer:

Önceki karakter bir kelimenin parçasıysa, geçerli karakter bu sözcüğe eklenir.

Bu ipinizi kapsar ab$.

Yalnız bir durumda $("yeni kelime" tek başına olurdu $):

Geçerli karakter yeni bir sözcüğün başlangıcı olarak kullanılır.

Anlamı , bir içeren üretilen kelimenin $standart genişleme açıkça POSIX tarafından tanımlanmamış olarak tanımlanır değildir.

Ayrıca $, içindeki son karakter olduğunu $$, ancak bunun geçerli kabuğun PID'sini tutan değişken olduğunu da unutmayın . In bash, !$bir geçmiş genişletme (önceki komuttan son argüman) çağırabilir. Yani, genel olarak, hayır, $alıntılanmamış bir kelimenin sonunda anlamsız değildir, ancak bir kelimenin sonunda en azından standart bir genişlemeyi göstermez.


7

Kesin duruma bağlı olarak, bu ya açık bir şekilde belirtilmez (böylece uygulamalar olması gerektiği gibi yapılabilir) veya gözlemlediğiniz gibi gerçekleşmesi gerekir. Tam olarak senaryoda echo ab$, POSIX sen gözlemlenen "ab $" çıkışını zorunlu kılan ve onu belirtilmemiş değildir . Tüm farklı vakaların kısa bir özeti sonunda.

İki unsur vardır: önce kelimelere tokenleme, sonra bu kelimelerin yorumlanması.


Tokenisation

POSIX tokenizasyonu,$ geçerli bir parametre genişletmesi , komut ikamesi veya aritmetik ikamenin başlangıcı olmayan bir kodun, oluşturulmakta olan simgenin gerçek bir parçası olarak kabul edilmesini gerektirir WORD. Bunun nedeni, kural 5'in ("Geçerli karakter sıralanmamışsa $veya `kabuğun, başlangıçtaki sıralanmamış karakter dizilerinden parametre genişletme, komut ikamesi veya aritmetik genişletme için adayların başlangıcını tanımlaması gerekir: $veya ${, $(veya `, ve $((," ) geçerli değildir, çünkü bu genişletmelerin hiçbiri geçerli değildir. Parametre genişletmesi, orada görünmesi için geçerli bir ad gerektirir ve boş bir ad geçerli değildir.

Bu kural geçerli olmadığından, geçerli olanı bulana kadar takip etmeye devam ediyoruz. İki aday # 8'dir ("Önceki karakter bir kelimenin parçasıysa, geçerli karakter bu sözcüğe eklenmelidir.") Ve # 10 ("Geçerli karakter yeni bir sözcüğün başlangıcı olarak kullanılır.") , echo a$ve echo $sırasıyla uygulanır .

echo a$+bAynı çatlaktan geçen formun üçüncü bir vakası da vardır , çünkü +özel bir parametrenin adı değildir. Bu, daha sonra geri döneceğiz, çünkü kuralların farklı bölümlerini tetikliyor.

Dolayısıyla, spesifikasyon $sözdiziminin sözdiziminin bir parçası olarak düşünülmesini gerektirir ve daha sonra daha sonra işlenebilir.


Kelime genişletme

Giriş, bu şekilde ayrıştırıldıktan sonra $, sözcüğe dahil edildiğinde, okunan kelimelerin her birine sözcük genişletmeleri uygulanır. Her kelime ayrı ayrı işlenir .

Belirtildi :

Alıntılanmamış bir '$' ifadesinin ardından aşağıdakilerden biri olmayan bir karakter gelirse:

  • Sayısal bir karakter
  • Özel parametrelerden birinin adı (bkz. Özel Parametreler )
  • Değişken adının geçerli bir ilk karakteri
  • A <left-curly-bracket>('{')
  • bir <left-parenthesis>

sonuç belirtilmemiş.

"Belirtilmemiş" burada özel bir terimdir.

  1. Uygun bir kabuk bu durumda herhangi bir davranış seçebilir
  2. Uygun bir uygulama belirli bir davranışa güvenemez

Örnekte, echo ab$, $ takip etmiyorsa herhangi karakteri bu kural geçerli değildir bu yüzden ve tanımlanmamış sonuç çağrılmaz. Basitçe tahrik edilen bir genişleme yoktur $, bu yüzden tam anlamıyla mevcut ve basılır.

Nerede olacağını uygulamak yukarıdan üçüncü durumda geçerli: echo a$+b. İşte $izlemektedir +(Sayı, özel parametre olmadığı, @, *,# , ?, -, $, !, ya da 0), değişken bir başlangıç adı (alt çizgi veya bir alfabetik taşınabilir karakter kümesi ) ya da parantez biri. Bu durumda, davranış belirtilmez: uygun bir kabuğun genişleme adı verilen özel bir parametre icat etmesine izin verilir+ ve uygun bir uygulama kabuğun bunu yapmadığını varsaymamalıdır . Kabuk, bir hata bildirimi de dahil olmak üzere sevdiği başka her şeyi yapabilir.

Örneğin, zsh, kendi POSIX modunda da dahil olmak üzere , yorumlanması $+b"değişkendir olarak bgrubu" ya da ve yerine yerine 1 ya da 0. Benzer şekilde ~ve için uzantılar vardır =. Bu uygun davranıştır.

Bunun olabileceği başka bir yer echo "a$ b". Yine, kabuğun istediği gibi yapmasına izin verilir ve senaryo yazarı olarak $sizden gerçek çıktı istiyorsanız. Bunu yapmazsanız işe yarayabilir, ancak ona güvenemezsiniz. Bu şartnamenin mutlak mektubu, ancak bu tür ayrıntıların amaçlandığını veya dikkate alındığını düşünmüyorum.


Özetle

  • echo ab$: tam çıktı, tam olarak belirtilmiş
  • echo a$ b: tam çıktı, tam olarak belirtilmiş
  • echo a$ b$: tam çıktı, tam olarak belirtilmiş
  • echo a$b: parametrenin genişletilmesi b, tam olarak belirtilmiş
  • echo a$-b: özel parametrenin genişletilmesi -, tam olarak belirtilmiş
  • echo a$+b: belirtilmemiş davranış
  • echo "a$ b": belirtilmemiş davranış

Bir İçin $Bir kelimenin sonunda, sen davranışa güvenmek izin verilir ve tam anlamıyla tedavi ve aktarılması gereken echo, bağımsız değişkeni bir parçası olarak komuta. Bu kabuk üzerinde bir uyumluluk gereksinimidir.


Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
terdon

@MichaelHomer echo $Gerçek ve tam olarak belirtilebilir mi?
Harold Fischer

@HaroldFischer Evet
Michael Homer

Nerede echo "$"ve echo "a b$"düşüyor?
Harold Fischer
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.