Ksh cinsinden “[[” ve “-e xxx” arasında bir boşluk neden gereklidir?


9

Örneğin, aşağıdaki komut çalışmaz:

if [[-e xyz]]; then echo File exists;fi

ksh aşağıdaki hatayı verir

[[-e: command not found

Bunun nedeni "[[-" belirsiz mi?


2
[[bir anahtar kelimedir - muhtemelen kabuğun ayrıştırma ağacı, anahtar kelimelerin boşlukla tanımlanmasını gerektirir
steeldriver

Buna bakmanın bir başka yolu muhtemelen bir fonksiyon [[-, kabuğun e fonksiyonunu [do - e ”yerine“ ['' üzerindeki “bayrağını ayrıştırmayı nasıl bileceğini” yazmanızdır.
pbhj

Yanıtlar:


15

En basit açıklama olurdu, çünkü kılavuzda öyle görünüyor [[ expression ]]ki [[ve arasında expressionve kapanışında boşluk olması gerekiyor ]]. Ama elbette daha derinlemesine bakmayı deneyebiliriz. Kabuklar biraz karmaşık gramerlere sahiptir ve "kelime bölme" kavramına büyük ölçüde güvenir. Özellikle, ksh (1) manuel durumları:

Kabuk girdisini sözcüklere bölerek ayrıştırmaya başlar. Karakter dizisi olan kelimeler, sıralanmamış boşluk karakterleri (boşluk, sekme ve yeni satır) veya meta karakterler (<,>, |,;, &, (ve)) ile sınırlandırılır. Kelimeler sınırlandırılmasının yanı sıra, boşluklar ve sekmeler yok sayılırken, yeni satırlar genellikle komutları sınırlar.

Bu yüzden kılavuzda belirtildiği gibi, karakter dizisi [[-ebir kabuk kelimesi olarak kabul edilir. kshyerleşik komutlar ve özel işleçler ( forveya gibi while) listesinde böyle bir komut arar, sonra harici bir komut arar - ve voilà - hiçbiri bulunamadı, dolayısıyla komutla ilgili bir hata iletisi var.

Bu durumda [[özel meta karakterler de yoktur. Eğer öyle olsaydı , içindeki -ekısım kendi başına [[-ebir argüman değil, bir kabuk kelimesi olarak kabul [[edilirdi. Bununla birlikte, [[bileşik komut olarak tanımlanır ve kılavuzda aşağıdakiler söylenir:

Bileşik komutlar, aşağıdaki ayrılmış sözcükler kullanılarak oluşturulur - bu sözcükler yalnızca tırnak işaretleri olmadan ve bir komutun ilk sözcüğü olarak kullanılırsa tanınır (yani, parametre atamaları veya yeniden yönlendirmelerden önce gelemezler):

Dolayısıyla, [[bir bileşik komut olarak tanınabilmesi için , bir komutun veya komut listesinin ilk sözcüğü olması gerekir; bu, daha önce bir "sözcük" tanımıyla, boşluklardan, sekmelerden veya diğer satırlardan yeni satırlarla ayrılması gerektiğini ima eder kelimeler / argümanlar.


Yorumlarda şunu sordunuz : "Ayrıştırıcı neden bulur bulmaz durmuyor" [["kalıbı ve bunu koşullu bir komutun başlangıcı olarak kabul ediyor?" Kısa cevap muhtemelen 1) [sözdiziminin etkisi aslında harici bir komut olduğu ve POSIX standart uyumluluğu için bugün bile harici komut olarak var olduğu ve 2) kabuk ayrıştırıcısı böyle oluşturulduğundan dolayıdır. Kabuk ayrıştırıcı, boşlukla sınırlandırılmış diğer özel karakterleri tanıyabilir: echo $((2+2))ve (echo foobar)mükemmel çalışır. Belki de gelecekte kshgelişim devam ettiğinde mkshveya pdkshbiri çatalsız veya klon gibi göründüğünde ( ya da gibi ) birisi boşluksuz sözdizimi uygulayacaktır [[-e.

Ayrıca bakınız:


3
Ksh manuel teklif gerçekten yerinde olduğunu düşünüyorum. Diğer herhangi bir programlama diline benzer: C dilinde char, bir anahtar kelimedir, ancak yine de charsomeletter = 'A';ayrıştırıcıyı gördükten sonra yazamaz ve durmasını bekleyemezsiniz char.
Peter - Monica'yı

Bence "char" örneğiniz ile sorudaki "[[" sembolü arasındaki temel fark, genel olarak alfasayısal bir tanımlayıcının diğerlerinden ayırmak için boşluk ayırıcıya ihtiyaç duymasıdır; jeton olarak özel semboller ise boşluk sınırlayıcılara ihtiyaç duymaz.
AcBap

Kesinlikle. C ile karşılaştırmanın faydalı olduğuna emin değilim. C olarak söylenebilir i--<=++jve derleyicinin bunu ayrıştırma sorunu yoktur i -- <= ++ j.
Scott

@Scott, C karşılaştırmasının yararlı olduğunu düşünüyorum (ve C tanımlayıcılarının yalnızca alfasayısallara izin verdiği ve ikincil bir şekilde _). Ksh (bir operatör olarak vardır ve (echo hello)ayrıştırır ( echo hello ). Bu gelmiştir if, {, [[ve diğer anahtar kelimeler ve ifx, {xve [[xher biri belirteci olan - nasıl böyle charsomeletterbir C belirteci olduğunu. Buna karşılık, (xksh'ta sıralanmamış iki simge - i--C'deki iki simge gibi. Bir operatör olmanın kavramsal olarak bile anlamı Bourne tarzı mermiler (ksh gibi) ve C arasında farklılık gösterir. Ancak Peter A. Schneider bir gerçek sözcüksel benzerlik.
Eliah Kagan

2

Dikkat edilmesi gereken önemli olan [bir komuttur ve [[bash ve ksh içindeki shell anahtar sözcüğünü temel alır [.

[[ile benzer şekilde kullanılır [. Bazen hatta yerini alabilir [ ]ile [[ ]]davranışında hiçbir değişiklik olmadan. İle [, herhangi bir komuta gibi, bir uzay komuta ve argümanları arasında zorunludur. Aynı şey için de geçerlidir [[.

Eskiden sadece vardı /usr/bin/[. Artık çoğu mermi [verimlilik için inşa edilmiştir - ancak sözdizimi aynıdır. Sağlayan mermilerde, daha çok yönlü bir alternatif [[olarak işlev görür .[

İşte [bash için açıklama :

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

Yani [eşdeğerdir test( ]en sonunda bir argüman beklemek dışında ). help testüzerinde daha fazla ayrıntı verecek. Bunu ile karşılaştırabilirsiniz help [[.

Harici komut için bir kılavuz sayfası da vardır [( man \[).

Bu durumuda

if [[-e
  • Ne bir komut ne [de [[orada. Tam kelime [[-e.
  • Bunu if [[-edoğru / yanlış testi yapar. Peki bir komut [[-evar mı?

Bunun nedeni "[[-" belirsiz mi?

Evet. Ya da hayır. [[-ene olduğu: kabuğun anladığı hiçbir şey, bu yüzden kendi emri olduğunu varsayar. ;-)


"% help [[", "[[" koşullu bir komut olduğunu söylüyor. Ayrıştırıcı neden "[[" kalıbını bulur bulmaz durmaz ve bunu koşullu bir komutun başlangıcı olarak görür?
AcBap

@Myloti [[-epotansiyel olarak geçerli (garip görünüyorsa) bir komut adıdır.
Gordon Davisson

2

Alan bir sınırlayıcıdır ve gereklidir. Gördüğünüz gibi shellcheck:

$ shellcheck gmail-browse-msgs-algorithm.sh

In gmail-browse-msgs-algorithm.sh line 847:
        [[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
          ^-- SC1035: You need a space after the [[ and before the ]].

(Hem ksh hem de bash desteği vardır [[ve boşluk olmadan çalışmaz. Shellcheck tam olarak bu satırı içeren benzer ksh ve bash komut dosyalarıyla çıktı verir.)

Sınırlayıcılara neden ihtiyaç duyulduğunu belirteçler ve sözlükçelerle ilişkilendirmek gerekir .


Lütfen dikkat, OP kshsoruda kabuk hakkında sordu . Bash ödünç [[gelen operatörü kshve onların davranışları aynıdır bu soruda, ancak arasında bazı önemli farklılıklar var gibi ben varsayımların temkinli olacağını kshve bashdavranış ve iç yapıları. Bunun nedeni, shellcheck'in bash betiği üzerinde çalışması nedeniyle, ksh betikleri için uygun bir araç olmayabilir. Farklı kabuklara yaklaşırken akılda tutulması gereken bir şey
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy Yerleşik [[kuralları vurgulamak için shellcheck kullanarak fırsatçı oluyordum . Hiçbir şekilde bunun hata bulabilen kshbir kabuk olduğu anlamını yitirmedim shellcheck. Umarım başkaları takdir eder kshve bashiki farklı tercümandır. Bundan bahsettiğiniz için teşekkürler. Ayrıca , harici bir komut [[iken inşa edilmiş bir bash da dikkat çekicidir [.
WinEunuuchs2Unix

Aslında [bash yerleşik bir :) :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Ama çok uzakta değilsiniz - [veya testharici bir komut olması gerekiyor. Orijinal Bourne kabuğunun günlerinde [aslında harici bir komut vardı ve günümüzde hala /usr/bin/[POSIX bunun harici bir komut olmasını gerektirdiği için var. Pubs.opengroup.org/onlinepubs/009695399/utilities/test.html POSIX için çok az şey gerekiyor yerleşik pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Yerleşiklik [verimlilik içindir
Sergiy Kolodyazhnyy

2
Shellcheck bilir ksh; bir hashbang kullanın veya -s ksh. Btw, ksh ve bash [["yerleşik", ancak aksine , bir kabuk yerleşik olan bir anahtar kelime . (ksh :; bash :) Yerleşikler ve harici komutlar sözdizimsel olarak birbirine benzer. Tek yönlü gelen farklılık olduğunu kadar - bir yerleşiğini olarak olamazdı Bağımsız değişkenlerinin, içinde bastırır bazı açılımlar gruplama yapamadık bunun bir yerleşik idi. Bu (veya ) bir token olmanın garip hissetmesinin nedeni olabilir . Bence buildins ve anahtar kelimelerin sözcüksel ama sözdizimsel olarak benzer olmadığını söylemek doğru . @SergiyKolodyazhnyy[whence -v [ [[type [ [[[[[[[{{x[[x
Eliah Kagan

1
@EliahKagan Aslında, POSIX'in bu durum hakkında ne düşündüğüne dair kesin bir cevap almak için U&L üzerine bir soru yayınladım unix.stackexchange.com/questions/526574/… Kabuk dili yeterince karmaşık, umarım birisi daha resmi terimlerle açıklayabilir
Sergiy Kolodyazhnyy

1

[[harici bir komut olabilir! Yani, bir program olabilir ve kabuğunuz tarafından doğrudan desteklenen bir sözdizimi olmayabilir. Boşluksuz bir sözdizimini desteklemek mümkün olabilir, kshancak harici sistemlerde başarısız olur, [[bu nedenle uyumluluk nedeniyle gerekli alanı tutmak daha iyidir.

[[Mesela BusyBox harici bir komut sağlıyor .


0

İtibaren [[-ekabuk genişleme katılabilir (bu gibi kullanılabilir

echo [[-e]*

arasında [ve edahilinde bir harfle başlayan tüm dosyaları listelemek için ), normal boşluklarla yönetilen kelime bölünmesine katılmayan özel karakterler olsaydı [ve tam bir karmaşa olurdu ].

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.