bash에서 파이프 (|) 및 논리 및 (&&)의 우선 순위 ls screenshot* | head -n 5) 그리고

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 5cd ~/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출력이 없기 때문에 에테르 방식으로 차이가 없습니다.


답변