Neden metakarakterlerin çevresinde boşluk gerekir?


543

Birkaç ay önce koluma çatal bombası attım ve boşlukları atladım, çünkü bence onlarsız daha güzel görünüyor. Ama benim dehşetime, bazen (her zaman değil) bir kabukta çalıştırdığımda çatal bombası başlatmıyor, ama sadece bir sözdizimi hatası veriyor.

bash: syntax error near unexpected token `{:'

Dün bir arkadaşımın Bash kabuğunda çalıştırmaya çalıştığımda oldu ve sonra boşlukları ekledim ve aniden çalıştı, :(){ :|:& };:yerine:(){:|:&};:

Boşluk önemli mi? Kolumda bir sözdizimi hatası mı buldum ?!

Her zaman zsh ile çalışıyor gibi görünüyor , ama Bash'de değil.

İlgili bir soru , gerçekten benim sorum olan boşluklar hakkında hiçbir şey açıklamıyor; Bash'in onu doğru şekilde ayrıştırması için neden boşluk gerekiyor?


6
Aynı soruyu buraya da gönderdim (dövme kısmı hariç).
Benoit

3
Ayrıca, iki nokta üst üste (:) işlev adı olarak kullanılamaz (bkz: pubs.opengroup.org/onlinepubs/9699919799/utilities/… ) ... FreeBSD / bin / sh bile bu konuda bir hata veriyor ...
Martin Tournoij

5
@Carpetsmoker: Bunun ne kadar alakalı olduğundan emin değilim. Bu sorular Bash hakkında.
Dennis

Yanıtlar:


267

BASH'de jetonları ayıran karakterlerin bir listesi var. Bu karakterler denir meta karakterler olduklarını ve |, &, ;, (, ), <, >, uzay ve sekme . Öte yandan, kıvırcık parantezler ( {ve }) sadece kelimeleri oluşturan sıradan karakterlerdir.

Daha önce ikinci boşluğu atlamak }, çünkü &bir metakarakterdir. Bu nedenle, dövmeniz en az bir boşluk karakterine sahip olmalıdır.

:(){ :|:&};:

35
Kolay çözüm: taoo'nun ilk kısmını iki parça arasında sola ve nakil cildine doğru hareket ettirin.

23
Terim hoşuma gitti, on the other hand... cinas amaçladı? ;): D (Üzgünüm, konu dışı yorum için.)
anishsane

4
Ama bu zsh için farklı mı? Zsh hangi yönden farklıdır?
tfogo

2
İyi açıklama, o hariç {ve }olan kabuk anahtar kelimeler bu bağlamda. Sadece böyle tanınmazlarsa - çevreleyen alanların / meta karakterlerin eksikliği nedeniyle - parçası oldukları kelimenin gerçek bir parçası olarak kabul edilirler. (Ve sonra farklı bir bağlamda gerçekleşen
küme

2
@DmitriChubarov Komut adlarında parantezlere izin verilir (işlevler dahil:. {foo} () { echo hello; }"Ad", bash"yalnızca alfasayısal karakterler ve alt çizgilerden oluşan ve alfabetik bir karakter veya altçizgi ile başlayan" olarak tanımlandığı gibi, yalnızca değişken adları için geçerlidir.
chepner

82

Sadece dövme

#!/bin/zsh

üzerinde shebang ve iyi olacaksın.


6
Seçici olursak, koç hiç işe yaramaz, çünkü kabuk, umarım zsh, istemin de kanıtladığı gibi interaktif
moddadır

50

Kaşlı ayraçlar, özel sembollerden çok tuhaf anahtar kelimeler gibidir ve boşluklara ihtiyaç duyar. Örneğin parantezlerden farklıdır. Karşılaştırmak:

(ls)

hangi çalışır ve:

{ls}

adında bir komut arar {ls}. Çalışmak için şunlar olmalı:

{ ls; }

Noktalı virgül, kapanış parantezinin parametre olarak alınmasını durdurur ls.

Tek yapmanız gereken insanlara oldukça dar bir boşluk karakteri olan orantılı bir yazı tipi kullandığınızı söylemek.


12
@DmitriChubarov - tamamen farklı bir parantez anlamı kullanan çok sinsi bir numara. Virgülle ayrılmış değerler listesini genişletir, bu durumda yalnızca ls.
Peter Westlake

7
Ama… oğlum… hayatının geri kalanında dövme yapacaksın! Kendinizi her zaman bir inek olarak işaretlediniz! Ve sonra dikiş yapmadan hemen önce anlayamadınız mı? Sanırım nerdy olmanın iki adımı ötesinde sanırım ;-) Hiçbir suç, dostum, sadece merak ediyorum.
Alfe

14
@Alfe Dövmeden önce denedim, ama zsh'ımda denedim, bash ile aynı ayrıştırma olduğunu düşündüm. Beni aptal yerine koyuyorum ama insanlara bunun zsh olduğunu söyleyeceğim. :)
Ocak'ta spydon

20
@spydon Ya da dövme gelen komutu kopyalayarak o insanların yanlışlıkla çalıştırmak ve onların makineyi çökme olmaz böylece bilerek alanı dışında kalan söyle;)
dürtmek

4
Hey, eğer zsh için geçerliyse, neden sadece üstüne #! / Bin / zsh eklemeyin? Her neyse, önce kabuğu belirtmek iyi bir uygulamadır.
Adam Miller

41

Dövme yazı tipinde kolayca görünmese de, aslında küme ve kolon arasında bir Byte-Order İşareti (BOM) vardır (farketmediğiniz dövmeyi aldığınızda yeterince sarhoş olabilirsiniz, ama gerçekten orada) . Bu, üç belirgin olasılık bırakır:

  1. Kodu kopyaladığınızda Malzeme Listesini yazmayı başaramadınız. Sonuç, GIGO'nun bariz bir uygulamasıdır. Kabuk, başarısız transkripsiyonunuzda bulunmayan bir Malzeme Listesini tanımıyor.
  2. Kabuğun çok eski. Unicode karakterleri tanımıyor, bu nedenle BOM (ve muhtemelen diğer tüm Unicode karakterler), herhangi bir yerde bir BOM olmasına rağmen, dosyanın başlangıcının sıfır genişlikli, kırılmaz bir alan olarak kabul edilmesi gerekiyorsa, tamamen yok sayılıyor. .
  3. Kabuğun çok yeni. Bir Malzeme Listesinin ZWNBS olarak kullanımı onaylanmamıştır ve yazarlar, bu kullanıma artık izin verilmeyen gelecekteki bir Unicode sürümünü uygulamıştır.

40

ve sonra boşlukları ekledim ve aniden çalıştı ...

Kabuğun nasıl ayrıştığı yüzünden. İşlev tanımı başladıktan sonra, yani {.

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}

geçerli. Diğer yandan,

foo() {echo hey&}

değil.


Aslında böyle bir dövmeye ihtiyacınız var:

resim açıklamasını buraya girin


Gönderen kaynağı :

  /* We ignore an open brace surrounded by whitespace, and also
     an open brace followed immediately by a close brace preceded
     by whitespace.  */

{Nedenlerinden sonra boşluk {echobırakılması tek bir jeton olarak yorumlanmasına neden olur .


Eşdeğer bir formu

:(){ :|:& };:

olabilir

:(){
:|:& };:

{Alternatif sürümde sonra boşluk olmadığını , ancak satır kesmesinin kabuğun {bir belirteç olarak tanımasına neden olduğunu unutmayın .


"{Den sonra boşluk bırakılması {eko'nun tek bir belirteç olarak yorumlanmasına neden olur." - ayrıştırıcı {echogerekli açılış parantezine ulaşmadan önce çağrılan bir komutla karşılaştığına inanıyor mu?
Jonah
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.