답변:
단순화 된 이유는 한 문자가 존재하기 때문입니다 space.
중괄호 확장은 인용되지 않은 공백을 처리하지 않습니다.
{...}
목록 에는 인용 부호가없는 공백이 필요합니다.
보다 자세한 대답은 쉘이 명령 행을 구문 분석하는 방법 입니다.
명령 행을 구문 분석 (이해)하는 첫 번째 단계는 명령 행을 여러 부분으로 나누는 것입니다.
이러한 부분 (일반적으로 단어 또는 토큰이라고 함)은 명령 줄을 각 메타 문자 에서 링크와 구분하여 생성됩니다 .
- 고정 메타 문자 세트 (SPACE, TAB, NEWLINE,;, (,), <,>, | 및 &)로 구분 된 토큰으로 명령을 분할합니다. 토큰 유형에는 단어, 키워드, I / O 리디렉터 및 세미콜론이 포함됩니다.
메타 문자 : spacetabenter;,<>|및 &.
분할 후 단어는 (쉘에서 이해되는) 유형일 수 있습니다.
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
"괄호 문자열"(공백 또는 메타 문자가없는)이 단일 단어이고 (위에서 설명한대로) 인용되지 않은 경우에만 "중괄호 확장"의 후보입니다. 내부 구조에 대한 추가 점검은 나중에 수행됩니다.
따라서, 이는 : {ls,-l}
될 "가새 확장"자격 ls -l
으로하거나, first word
또는 argument
(zsh을는 떠들썩한 파티에서 다르다).
$ {ls,-l} ### executes `ls -l`
$ echo {ls,-l} ### prints `ls -l`
그러나 이것은 : {ls ,-l}
. 배쉬에서 분할합니다 space및 두 단어로 라인을 구문 분석 : {ls
하고 ,-l}
있는이 트리거 command not found
(인수가 ,-l}
손실됩니다)
$ {ls ,-l}
bash: {ls: command not found
귀하의 라인 : {ls;echo hi}
때문에의 "중괄호 확장"가되지 않습니다 이 메타 문자 ;와 space.
다음 세 부분으로 나뉩니다. {ls
새 명령 : echo
hi}
. ;트리거가 새 명령의 시작을 트리거 한다는 것을 이해하십시오 . 명령 {ls
을 찾을 수 없으며 다음 명령이 인쇄됩니다 hi}
.
$ {ls;echo hi}
bash: {ls: command not found
hi}
다른 명령 뒤에 배치되면 어쨌든 다음에 새 명령이 시작됩니다 ;.
$ echo {ls;echo hi}
{ls
hi}
"복합 명령"중 하나는 "중괄호 목록"(내 단어) { list; }
입니다.
보시다시피 공백과 닫는 것으로 정의됩니다 ;
.
공간과는 ;모두 있기 때문에 필요 {
하고 }
"예약 된 단어 ".
따라서 단어로 인식 되려면 메타 문자로 둘러싸 야합니다 (거의 항상 :) space.
링크 된 페이지 의 포인트 2에 설명 된대로
- 각 명령의 첫 번째 토큰을 검사하여 ...., {또는 ()인지 확인하십시오. 그러면 명령이 실제로 복합 명령입니다.
귀하의 예 : {ls;echo hi}
목록이 아닙니다.
;뒤에 닫히고 하나 이상의 공백 이 필요합니다 {. 마지막 }은 닫는 것으로 정의됩니다 ;.
이것은 목록 { ls;echo hi; }
입니다. 그리고 이것은 { ls;echo hi;}
또한 (일반적으로 덜 사용되지만 유효합니다) (@choroba의 도움에 감사드립니다).
$ { ls;echo hi; }
A-list-of-files
hi
그러나 명령에 대한 인수 (쉘은 차이점을 알고 있음)로 오류를 트리거합니다.
$ echo { ls;echo hi; }
bash: syntax error near unexpected token `}'
그러나 쉘이 구문 분석하고 있다고 믿는 것에주의하십시오.
$ echo { ls;echo hi;
{ ls
hi
;
와 사이에 공백이 필요하지 않습니다 }
. { ls;}
세미콜론은 이미 메타 문자로 작동합니다.
블록 {
은 쉘 키워드이므로 공백으로 다음 단어와 구분해야하며 중괄호 확장에는 공백이 없어야합니다 (공백 확장 공백을 사용해야하는 경우에는 이스케이프해야합니다. echo {\ ,a}{b,c}
).
명령 시작시 괄호 확장을 사용할 수 있습니다.
{ls,.} # expands to "ls ."
확장 전에 그룹화 명령 구문 분석이 발생하므로이를 사용하여 블록으로 확장 할 수 없습니다.
echo {'{ ls','.;}'} # { ls .;}
{'{ ls','.;}'} # bash: { ls: No such file or directory
명령 줄의 구문을 확인하여 알 수 있습니다. 같은 식으로 echo echo
, 표현식 에서 첫 번째 에코는 명령으로 처리되고 두 번째 에코는 첫 번째 에코의 매개 변수로 처리되어야합니다.
bash에서는 { cmd; }
공백과 세미콜론이 있어야 하므로 매우 간단 합니다. 그러나 예를 들어 zsh에서는 필요하지 않지만 여전히 {}
셸 컨텍스트를 분석 하여 내용으로 수행해야 할 작업을 알 수 있습니다.
다음을 고려하세요:
alias 1..3=date
{ 1..3; } #in bash
{1..3} #in zsh
둘 다 현재 날짜를 반환하지만
echo {1..3}
1 2 3
shell은 {}
command의 인수를 알고 있기 때문에 반환 되므로 echo
확장해야합니다.
{
따옴표없는 공간이 뒤에 오는 것은 bash에서 괄호 확장을 시작하지 않습니다.
{
. 쉘이 전체 명령 행을 공백으로 분할하므로 인용되지 않은 공간은 어디에도있을 수 없습니다.
먼저 복합 중괄호는 단어 자체와 명령 줄의 첫 번째 단어 여야합니다.
echo { these braces are just words }
둘째, 개별 괄호는 특별하지 않습니다 (위에서 볼 수 있듯이). 빈 괄호도 특별하지 않습니다 :
echo {} # just the token {}: familiar from the find command
쉼표가없는 것도 그 자체입니다
echo {abc} # just {abc}
여기에서 작업이 시작됩니다.
echo {a,b} # braces disappear, a b results.
따라서 기본적으로 중괄호 확장을 시작하려면 하나 이상의 단어 (공백에서 필드로 분리되지 않음)가 필요합니다. 내부 {...}
에는 적어도 하나의 쉼표가있는 내부 인스턴스가 하나 이상 있습니다.
이것은 명령 행에서 첫 번째 단어 가 될 수 있습니다.
{ls,-l} . # just "ls -l ."
{
명령의 시작 부분에 표시되면 명령 목록으로 해석되고 그렇지 않으면 중괄호 확장으로 해석되는 것처럼 보이지만 확실하지 않습니다.