Operator Precedence의 기본 시나리오는 다음과 같습니다.
(cd ~/screenshots/ && ls screenshot* | head -n 5)
그리고 당신은 그것이 파싱되는지 ((A && B) | C)
또는 (A && B | C)
…
거의 공식 문서가 발견 여기에 단순히 표에서 확인 할 수 있도록 목록에 파이프를 나열하지 않습니다.
또한 bash에서는 (
작업 순서 변경뿐만 아니라 하위 셸을 생성 하므로이 줄이 이전 줄과 동일하다는 것을 100 % 확신하지 못합니다.
((cd ~/screenshots/ && ls screenshot*) | head -n 5)
더 일반적으로 bash 줄 의 AST 를 아는 방법은 무엇 입니까? 파이썬에는 트리를 제공하는 기능이있어 작업 순서를 쉽게 다시 확인할 수 있습니다.
답변
cd ~/screenshots/ && ls screenshot* | head -n 5
이것은
cd ~/screenshots && { ls screenshot* | head -n 5 ; }
( 중괄호는 서브 쉘없이 그룹 명령을 함께 묶습니다 ). 따라서의 우선 순위는 및 |
보다 높습니다 (바인드가 더 강합니다) . 그건,&&
||
A && B | C
과
A || B | C
항상 B의 출력 만 C에 주어져야 함을 의미합니다 . 필요한 경우 명확성을 위해 단일 엔티티로 명령을 사용 (...)
하거나 { ... ; }
결합 할 수 있습니다 .
{ A && B ; } | C
A && { B | C ; } # This is the default, but you might sometimes want to be explicit
몇 가지 다른 명령을 사용하여이를 테스트 할 수 있습니다. 당신이 실행하는 경우
echo hello && echo world | tr a-z A-Z
그럼 당신은 얻을 것이다
hello
WORLD
back : tr a-z A-Z
입력을 대문자echo world
로하고, echo hello
그 자체 만으로 연결되어있는 동안에 만 입력 된 것을 볼 수 있습니다 .
이것은 됩니다 에 정의 쉘 문법 : 아니지만 정말 명확하게 and_or
(생산 &&
/ ||
AA가 정의된다) pipeline
동안, 몸에를 pipeline
단지 포함 command
하는, 하지 않는 포함 and_or
단지 – complete_command
생산에 도달 할 수 있습니다 and_or
, 그리고 그것은 단지 존재 함수와 루프와 같은 구조적 구조의 몸체와 최상위 내부.
해당 문법을 수동으로 적용하여 명령에 대한 구문 분석 트리를 얻을 수 있지만 Bash는 자체적으로 아무것도 제공하지 않습니다. 나는 자신의 파싱에 사용 된 것 이상의 쉘을 모른다.
셸 문법에는 반 공식적으로 만 정의 된 많은 특수 사례가 있으며 올바른 목표를 달성하는 것이 매우 중요합니다. 배쉬 자체조차도 때때로 잘못되었다 . 따라서 실용성과 이상은 다를 수있다.
구문을 일치시키고 트리를 생성하려고 시도하는 외부 파서가 있으며 가장 신뢰할 수있는 Morbig을 권장 합니다.
답변
TL; DR :와 같은 구분 기호를 나열합니다 ;
. &
, &&
및 ||
구문 분석 순서를 결정하십시오.
배쉬 설명서는 우리에게 알려줍니다 :
AND 및 OR 목록은 && 및 ||로 구분 된 하나 이상의 파이프 라인 시퀀스입니다. 각각 제어 연산자.
또는 Bash Hacker의 Wiki가 간결하게 넣는 방법
<PIPELINE1> && <PIPELINE2>
따라서 cd ~/screenshots/ && ls screenshot* | head -n 5
하나의 파이프 라인 ls screenshot* | head -n 5
과 하나의 간단한 명령이 cd ~/screenshots/
있습니다. 설명서에 따라
파이프 라인의 각 명령은 별도의 프로세스 (즉, 서브 쉘)로 실행됩니다.
반면에 (cd ~/screenshots/ && ls screenshot*) | head -n 5
하나의 파이프 라인이 있습니다. 왼쪽에는 서브 쉘이 있고 오른쪽에는 있습니다 head -n 5
. 이 경우 OP의 표기법을 사용하면(A && B) | C
다른 예를 보자.
$ echo foo | false && echo 123 | tr 2 5
$
여기에 하나의 목록이 <pipeline1> && <pipeline2>
있습니다. 파이프 라인의 종료 상태는 마지막 명령의 종료 상태와 같고 false
실패라고하는 음의 상태를 반환 &&
하므로 오른쪽을 실행하지 않습니다.
$ echo foo | true && echo 123 | tr 2 5
153
여기서 왼쪽 파이프 라인은 성공 종료 상태이므로 오른쪽 파이프 라인이 실행되고 출력이 표시됩니다.
쉘 문법은 실제 실행 순서를 의미하지 않습니다. Gilles의 답변 중 하나를 인용하려면 :
파이프 된 명령은 동시에 실행됩니다. ps를 실행할 때 | grep…, ps 또는 grep이 먼저 시작하는지 여부에 대한 추첨의 행운 (또는 쉘의 작업에 대한 세부 사항이 커널의 창자에 깊숙이 미세 조정 됨) 동시에 실행합니다.
그리고 bash 매뉴얼에서 :
AND 및 OR 목록은 왼쪽 연관성으로 실행됩니다.
에 그 바탕으로 cd ~/screenshots/ && ls screenshot* | head -n 5
은 cd ~/screenshots/
, 먼저 실행된다 ls screenshot* | head -n 5
이전 명령이 성공하면,하지만 head -n 5
첫 번째 프로세스가 아닌 산란 수 있습니다 ls
그들은 파이프 라인에 있기 때문에.
답변
여기에 지정된 위치가 있습니다 bash(1)
.
SHELL GRAMMAR
[...]
Pipelines
A pipeline is a sequence of one or more commands separated by one of
the control operators | or |&.
[...]
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ||, and optionally terminated by one of ;, &, or
<newline>.
따라서 &&
파이프 라인을 분리합니다.
답변
당신은 시도 할 수 있습니다 echo hello && echo world | less
. |
우선 순위가 높은 것을 볼 수 있습니다 (명령 파이프 라인은 명령 임). 두 번째 예제는 동일 하지 않습니다 . 그러나 cd
출력이 없기 때문에 에테르 방식으로 차이가 없습니다.