메타 문자 주위에 공백이 필요한 이유는 무엇입니까?


543

몇 달 전에 나는 팔에 포크 폭탄 을 문신했고 , 공백없이 건너 뛰었습니다. 그러나 셸에서 실행할 때 때때로 (항상 그런 것은 아닙니다) 포크 폭탄을 시작하지는 않지만 구문 오류가 발생합니다.

bash: syntax error near unexpected token `{:'

어제는 친구의 그것을 실행하려고 할 때 무슨 일이 있었 배쉬 쉘, 그리고 나는 공백을 추가하고 갑자기, 일을 :(){ :|:& };:대신:(){:|:&};:

공백이 중요합니까? 팔에 구문 오류가 있었나요?!

항상 zsh 에서는 작동 하지만 Bash에서는 작동 하지 않는 것 같습니다 .

관련 질문 은 공백에 대해 아무 것도 설명하지 않습니다. 실제로 내 질문입니다. Bash가 공백을 올바르게 구문 분석하려면 왜 공백이 필요합니까?


6
나는 같은 질문을 여기에 올렸다 (문신 부분 제외).
Benoit

3
또한 콜론 (:)은 함수 이름으로 사용할 수 없습니다 ( pubs.opengroup.org/onlinepubs/9699919799/utilities/… 참조 ) ... FreeBSD의 / bin / sh는 이것에 오류를줍니다
Martin Tournoij

5
@ Carpetsmoker : 그것이 어떻게 관련되어 있는지 잘 모르겠습니다. 이 질문은 배쉬에 관한 것입니다.
데니스

답변:


267

BASH에는 토큰을 구분하는 문자 목록이 있습니다. 이러한 문자라고 메타 문자 가 있고 |, &, ;, (, ), <, >, 공간 . 반면 중괄호 ( {})는 단어를 구성하는 일반 문자 일뿐입니다.

메타 문자 }이기 때문에 두 번째 공백을 생략하면 됩니다 &. 따라서 문신에는 하나 이상의 공백 문자가 있어야합니다.

:(){ :|:&};:

35
쉬운 해결책 : taoo의 첫 번째 부분을 왼쪽으로 옮기고 두 부분 사이에 피부를 이식하십시오.

23
나는 on the other hand말장난을 좋아했다 . ;) : D (죄송합니다, 주제 코멘트를 제외하고.)
anishsane

4
그러나 이것은 zsh와 다른가? zsh는 어떤면에서 다른가요?
tfogo

2
좋은 설명은 다음 사항을 제외시켰다 {하고 }있는 쉘 키워드 이러한 맥락이다. 주변 공간 / 메타 문자가 없기 때문에 인식되지 않는 경우에만 해당 단어가 문자의 일부로 취급됩니다. (그리고 다른 상황에서 발생하는 중괄호 확장이 있습니다.)
mklement0

2
@DmitriChubarov 중괄호는 명령 이름 (기능 포함 : {foo} () { echo hello; }. "이름" bash은 "영숫자 문자 및 밑줄만으로 구성되고 알파벳 문자 또는 밑줄로 시작하는 단어" 로 정의 됨)은 변수 이름에만 적용됩니다.
chepner

82

그냥 문신

#!/bin/zsh

그 위에 shebang 그리고 당신은 괜찮을거야.


6
만약 우리가 까다 롭다면, 쉘이 대화식 모드에 있기 때문에, 메시지에서 알 수 있듯이 shebang은 전혀 작동하지 않을 것입니다.
SzG

50

중괄호는 특수 기호보다 홀수 키워드와 비슷하며 공백이 필요합니다. 예를 들어 괄호와 다릅니다. 비교:

(ls)

작동하며

{ls}

라는 이름의 명령을 찾습니다 {ls}. 작동하려면 다음과 같아야합니다.

{ ls; }

세미콜론은에 대한 매개 변수로 닫는 중괄호가 중지됩니다 ls.

공간 문자가 다소 좁은 비례 글꼴을 사용한다고 사람들에게 알리기 만하면됩니다.


12
@DmitriChubarov-완전히 다른 의미의 괄호를 사용하는 매우 교묘 한 트릭입니다. 쉼표로 구분 된 값 목록을 확장합니다 (이 경우에는) ls.
피터 웨스트 레이크

7
그러나 ... 소년 ... 당신은 평생 동안 문신을 할 것입니다! 당신은 항상 자신을 머저리로 표시했습니다! 그리고 다음 당신도 바로이 스티치 가진 전에를 얻을 수 있을까? 그것은 nerdy가되는 것 이상의 두 단계이다. ;-) 공격, 친구, 나는 단지 궁금하다.
Alfe

14
@Alfe 문신하기 전에 시도했지만 zsh에서 시도했지만 bash와 동일한 구문 분석이 있다고 생각했습니다. 어리석은 일이지만 사람들에게 그것이 zsh라고 말할 것입니다. :)
spydon

20
@spydon 또는 당신은 당신이 당신의 문신에서 명령을 복사하는 사람들이 실수로 그것을 실행하지 않고 그들의 기계를 충돌하지 않도록 의도적으로 공간을 잃었다 고 말합니다.)
poke

4
이봐, 만약 그것이 zsh에서 유효하다면, 바로 위에 (또는 그 앞에) #! / bin / zsh를 추가하지 않는가? 어쨌든 먼저 쉘을 지정하는 것이 좋습니다.
Adam Miller

41

문신 글꼴에서 쉽게 볼 수는 없지만 실제로는 중괄호와 콜론 사이에 BOM (Byte-Order Mark)이 있습니다. . 이것은 세 가지 명백한 가능성을 남깁니다.

  1. 코드를 작성할 때 BOM을 입력하지 못했습니다. 결과는 GIGO의 명백한 적용입니다. 쉘은 단순히 실패한 기록에없는 BOM을 인식하지 못합니다.
  2. 껍질이 너무 낡았습니다. 유니 코드 문자를 인식하지 못하므로 BOM (및 기타 모든 유니 코드 문자)은 어디에서나 BOM이 아닌 파일의 시작이 폭이 0이 아닌 공백으로 취급 되더라도 BOM (또는 다른 모든 유니 코드 문자)은 완전히 무시됩니다. .
  3. 껍질이 너무 새롭습니다. BOM을 ZWNBS로 사용하는 것은 더 이상 사용되지 않으며, 작성자는이 사용이 더 이상 허용되지 않는 향후 유니 코드 버전을 구현했습니다.

40

그런 다음 공백을 추가하고 갑자기 작동했습니다 ...

쉘이 구문 분석하는 방식 때문입니다. 함수 정의가 시작된 후, 즉 뒤에 공백이 필요합니다 {.

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

유효합니다. 반면에

foo() {echo hey&}

그렇지 않습니다.


실제로 다음과 같은 문신이 필요합니다.

여기에 이미지 설명을 입력하십시오


로부터 소스 :

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

(가) 뒤에 공백을 생략 {원인 {echo하나의 토큰으로 해석 될 수 있습니다.


동등한 형태

:(){ :|:& };:

될 것이다

:(){
:|:& };:

{대체 버전 에는 공백이 없지만 줄 바꿈으로 인해 셸 {이 토큰 으로 인식 됩니다.


"{뒤에 공백을 생략하면 {echo가 단일 토큰으로 해석됩니다." 파서 {echo가 필요한 여는 중괄호에 도달하기 전에 호출 된 명령이 발생했다고 생각 합니까?
요나
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.