Echo ile beklenmedik davranış [[: digit:]]


10

Sormak istiyorum:

Neden olduğu echo {1,2,3}, beklenen bir davranıştır ki 1 2 3 genişletilmiş ederken echo [[:digit:]]döner [[:digit:]]ben tüm rakamları yazdırmak için beklenen süre 0için 9?


Yanıtlar:


34

Çünkü onlar iki farklı şey. Bu küme ayracı genişlemesine{1,2,3} bir örnektir . Yapı genişletilir kabuk tarafından önce bile görüyor. Kullandığınızda ne olacağını görebilirsiniz :{1,2,3}echoset -x

$ set -x
$ echo {1,2,3}
+ echo 1 2 3
1 2 3

Gördüğünüz gibi komut echo {1,2,3}şu şekilde genişletildi:

echo 1 2 3

Ancak, [[:digit:]]bir olan POSIX karakter sınıfı . Verdiğiniz zaman echo, kabuk da önce onu işler, ancak bu sefer bir kabuk küresi olarak işlenir . echo *geçerli dizindeki tüm dosyaları yazdıracak şekilde çalıştırdığınız gibi çalışır . Ancak [[:digit:]]herhangi bir rakamla eşleşen bir kabuk glob. Şimdi, bash'da, eğer bir kabuk küresi hiçbir şeyle eşleşmezse, kendisine genişleyecektir:

$ echo /this*matches*no*files
+ echo '/this*matches*no*files'
/this*matches*no*files

Glob bir şeyle eşleşirse, yazdırılacaktır:

$ echo /e*c
+ echo /etc
/etc

Her iki durumda da, echokabuğun yazdırmasını söylediği her şeyi yazdırır, ancak ikinci durumda, glob bir şeyle eşleştiği için ( /etc) buna bir şey yazdırması söylenir.

Bu nedenle, adı tam olarak bir rakamdan oluşan (veya [[:digit:]]eşleşecek olan) herhangi bir dosya veya dizininiz olmadığından , glob kendisine genişletilir ve elde edersiniz:

$ echo [[:digit:]]
[[:digit:]]

Şimdi, 5aynı komutu çağırıp aynı komutu çalıştırmayı deneyin :

$ echo [[:digit:]]
5

Ve birden fazla eşleşen dosya varsa:

$ touch 1 5       
$ echo [[:digit:]]
1 5

Bu, bu davranışı kapatan seçeneklerin man bashaçıklanmasında belgelenmiştir nullglob:

nullglob
    If  set,  bash allows patterns which match no files (see
    Pathname Expansion above) to expand to  a  null  string,
    rather than themselves.

Bu seçeneği ayarlarsanız:

$ rm 1 5
$ shopt -s nullglob
$ echo [[:digit:]]  ## prints nothing

$ 

4
Ayrıca shopt -s failglob, zshveya gibi modern kabuklara benzer daha yararlı bir davranış elde etmek için bakınız fish.
Stéphane Chazelas

Stéphane ile hemfikirim, kullan failglob. nullglobbeklenmeyen sorunlara neden olabilir, örneğin ?.
Kevin

1
Tabii, sadece nullglobdesenin kabuk tarafından bir glob olarak yorumlandığını göstermek için bahsettim .
terdon

14

{1,2,3}olan ayracı genişleme , onların anlamı bakılmaksızın listelenen kelimelerin genişler.

[...]dosya adı genişletmesinde (veya joker karakter veya glob) yıldız *ve soru işaretine benzer şekilde kullanılan bir karakter grubudur ?. İçinde listelenen herhangi bir karakterle veya listelenmiş gibi adlandırılmış grupların üyesi olan karakterlerle eşleşir [:digit:]. Kabukların çoğunun varsayılan davranışı, ona uyan hiçbir dosya yoksa joker karakteri olduğu gibi bırakmaktır.

(Bir joker karakteri / deseni eşleşeceği dizeler kümesine gerçekten çeviremeyeceğinizi unutmayın. Yıldız işareti herhangi bir uzunluktaki herhangi bir dizeyle eşleşebilir, bu nedenle onu içeren herhangi bir deseni genişletmek sonsuz bir dizi listesi üretecektir.)

Yani:

$ bash -c 'echo [[:digit:]]'           # bash leaves it as-is
[[:digit:]]
$ zsh -c 'echo [[:digit:]]'            # zsh by default complains if no match
zsh:1: no matches found: [[:digit:]]
$ touch 1 3 d i g t
$ bash -c 'echo [[:digit:]]'           # now there are two matches
1 3                                    # note that d, i, g and t do NOT match

Ama hala:

$ bash -c 'echo {1,2,3}'
1 2 3

Her ikisi de kabuk tarafından genişletilir , çalıştırdığınız komutun lsveya echoveya olması önemli değildir rm. Ayrıca, bunlardan herhangi biri alıntılanırsa, bunların genişletilmeyeceğini unutmayın:

$ bash -c 'echo "[[:digit:]]"'         # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}

Cevabınız için teşekkürler, linux için yeniyim, bu yüzden lütfen yankıların dosyalar ile nasıl ilişkili olduğunu sormama izin verin 1 3, işlevi bilgimi ile ilgili dosyaları
aramayan

1
@AbdAllahTalaat bunun yankı ile bir ilgisi yok aslında. Kabuk (örn. Bash), onu [[:digit:]] geçmeden önce "genişleyecektir" echo, bu yüzden echoasla görmez [[:digit:]], sadece görür 1 3. Çalışmakta set -xolan gerçek komutları yazdıracak şekilde çalıştırarak bunu görebilirsiniz ( set +xtekrar kapatmak için çalıştırın ).
terdon

@AbdAllahTalaat, çalıştırmadan önce echodosyaları aramaz, kabuk yapar echo.
ilkkachu

Özellikle DOS / Windows'da yardımcı programlar kabukları değil, joker karakterleri genişletiyor. (Belki yanılıyorum)
ilkkachu

Üzgünüm çocuklar tedron'un cevabına doğru cevabı kaydırdım çünkü yorumu bash'ın yankı olmayan işin ne olduğu anlamını içeriyordu ... yanıtı da bu anlamı içeriyordu .. hepiniz bana yardımcı oldu ... koyabilseydim diledim tüm cevap ve yorumlarınız için doğru cevap
AbdAllah Talaat

4

{1,2,3}(ör {1..3}olan bağ açılımları . Bunlar, komut yürütme önce kabuk tarafından yorumlanmaktadır.

[[:digit:]]bir desen eşleme jetonudur, ancak bunu bu desenle eşleşen herhangi bir dosyayla birlikte kullanmıyorsunuzdur. Eşleşmesi olmayan bir kalıp eşleşmesi kullanırsanız, kendi kendine genişler:

$ echo [[:digit:]]; touch 3; echo [[:digit:]]
[[:digit:]]
3

Hayır, diğer cevapların doğru bir şekilde belirttiği gibi, desen dosya adlarıyla eşleştirilir.
Toby Speight
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.