리디렉션과 관련된 하위 쉘의 우선 순위는 무엇입니까?

리디렉션과 관련된 하위 쉘의 우선 순위는 무엇입니까?

셸: GNU BASH

나는 한동안 다음 명령을 사용해 왔습니다.

echo "$(fmt -w 50 < foo.txt)" > foo.txt

문제 없습니다. 그러나 시도할 때:

fmt -w 50 < foo.txt > foo.txt

foo.txt 파일은 빈 파일이 됩니다. 이는 쉘에서 파싱하는 리디렉션 연산자가 서브쉘의 우선순위와 관련되어 있기 때문이라고 생각합니다.

GNU BASH 매뉴얼을 검색해도 결과가 나오지 않았습니다. 매뉴얼에 뭔가 빠졌는지 누군가 말해 줄 수 있나요? 저는 이 동작의 원인을 이해하여 이를 더욱 활용하고 문제를 일으킬 수 있는 모든 상황을 이해할 수 있기를 바랍니다.

답변1

Bash 매뉴얼에서,3.7.1 간단한 명령 확장:

간단한 명령을 실행할 때 셸은 왼쪽에서 오른쪽으로 다음과 같은 확장, 할당 및 리디렉션을 수행합니다.

  1. 파서에 의해 변수 할당으로 표시된 단어(명령 이름 앞의 단어)와 리디렉션은 나중에 처리하기 위해 저장됩니다.
  2. 변수 할당이나 리디렉션이 아닌 단어는 확장됩니다.쉘 확장). 확장 후 남은 단어가 있는 경우 첫 번째 단어는 명령 이름으로 처리되고 나머지 단어는 인수로 처리됩니다.
  3. 리디렉션은 위에 설명된 대로 수행됩니다(참조:리디렉션).
  4. 각 변수 할당 후의 텍스트는 =변수에 할당되기 전에 물결표 확장, 매개변수 확장, 명령 대체, 산술 확장 및 따옴표 제거를 거칩니다.

명령 대체는 (2)에서 발생하는 확장 중 하나이며, (3)에서 확장 후에 리디렉션이 발생합니다. 이는 서브쉘과 아무 관련이 없으며 순전히 쉘이 작업을 수행하는 순서 때문입니다. (fmt -w 50 < foo.txt) > foo.txt빈 파일도 생성됩니다.

답변2

사람들이 사용할 수sponge공익사업:

fmt -w 50 < foo.txt | sponge foo.txt

원문에 대한 참고사항:

echo "$(fmt -w 50 < foo.txt)" > foo.txt
  1. 가장 먼저 실행되는 것은 fmt출력이,큰따옴표로 묶인 내용입니다. fmt완료될 때까지 다른 일은 일어나지 않습니다 .

  2. echo문자열을 다음으로 인쇄합니다.표준 출력.

  3. 그 동안 echo출력은 >다음으로 리디렉션됩니다.foo.txt.

2단계와 3단계는 거의 동시에 발생합니다.

원래 코드에는 실제로 문제가 있습니다. 명령줄에는길이 제한. 당신이 입력하면foo.txt매우 크며, 특히 길이가 보다 큰 경우 getconf ARG_MAX명령 echo이 실패하거나 불완전한 결과를 제공합니다.

관련 정보