나는 그것이 {
중괄호 확장과 함께 작동한다는 것을 알았습니다.
echo {1..8}
또는 명령 그룹에서:
{ls;echo hi}
Bash는 차이점을 어떻게 알 수 있습니까?
답변1
간단한 이유는 문자가 존재하기 때문입니다: space.
브레이크 확장은 (인용되지 않은) 공백을 처리하지 않습니다.
목록에는 {...}
(인용되지 않은) 공백이 필요합니다.
더 자세한 답변은쉘이 명령줄을 구문 분석하는 방법.
명령줄을 구문 분석(이해)하는 첫 번째 단계는 명령줄을 여러 부분으로 나누는 것입니다.
이러한 부분(종종 단어 또는 토큰이라고 함)은 각 메타 문자에서 명령줄을 나누어 생성됩니다.링크에서:
- 명령을 고정된 메타 문자 집합(SPACE, TAB, NEWLINE, ;, (,), <, >, | 및 &)으로 구분된 토큰으로 분할합니다. 토큰 유형에는 단어, 키워드, I/O 리디렉터 및 세미콜론이 포함됩니다.
메타문자: spacetabenter;,<>|및 &.
분할 후 단어는 특정 유형을 가질 수 있습니다(셸에서 이해하는 대로).
- 명령 사전 할당:
LC=ALL ...
- 주문하다
LC=ALL echo
- 논쟁
LC=ALL echo "hello"
- 리디렉션
LC=ALL echo "hello" >&2
지원 확장
"중괄호로 묶인 문자열"(공백이나 메타문자 제외)이 (위와 같이) 단일 단어인 경우에만인용되지 않음, 이는 "브래킷 확장"의 후보입니다. 내부 구조에 대한 추가 검사는 나중에 수행됩니다.
따라서 이것은 "분기 확장"에 적합하며 , as 또는 (bash에서는 zsh가 다릅니다) {ls,-l}
이 될 수 있습니다 .ls -l
first word
argument
$ {ls,-l} ### executes `ls -l`
$ echo {ls,-l} ### prints `ls -l`
그러나 이것은 그렇지 않습니다: {ls ,-l}
. Bash는 행을 분할 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
답변2
block {
은 쉘 키워드이므로 다음 단어와 공백으로 구분해야 하며 중괄호 확장에는 공백이 있을 수 없습니다(중괄호 확장 공백이 필요한 경우 이스케이프해야 합니다: ) echo {\ ,a}{b,c}
.
명령 시작 부분에 중괄호 확장을 사용할 수 있습니다.
{ls,.} # expands to "ls ."
그러나 확장 전에 그룹화된 명령의 구문 분석이 발생하므로 이를 사용하여 블록으로 확장할 수는 없습니다.
echo {'{ ls','.;}'} # { ls .;}
{'{ ls','.;}'} # bash: { ls: No such file or directory
답변3
명령줄의 구문을 확인하여 이를 알 수 있습니다. 마찬가지로 표현식에서 echo echo
첫 번째 에코는 명령으로 처리되어야 하고 두 번째 에코는 첫 번째 에코에 대한 인수로 처리되어야 한다는 것을 알고 있습니다.
{ cmd; }
Bash에서는 공백과 세미콜론이 있어야 하므로 매우 간단합니다 . 그러나 예를 들어 zsh에서는 필요하지 않지만 {}
셸의 컨텍스트를 분석하면 해당 콘텐츠가 어떻게 처리되어야 하는지 알 수 있습니다.
다음을 고려하세요:
alias 1..3=date
{ 1..3; } #in bash
{1..3} #in zsh
둘 다 현재 날짜를 반환하지만
echo {1..3}
Return, 1 2 3
쉘은 {}
command 의 매개변수를 알고 있으므로 echo
확장되어야 합니다.
답변4
첫째, 복합 중괄호는 단어 자체여야 하며 명령줄의 첫 번째 단어여야 합니다.
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 ."