cat 명령이 명령 환경을 사용하지 않는 이유는 무엇입니까? [복사]

cat 명령이 명령 환경을 사용하지 않는 이유는 무엇입니까? [복사]

AFAIK는 스크립트 실행 cat과 마찬가지로 실행 시 새 프로세스를 포크하는 외부 명령입니다 . 그렇지만 다른 외부 명령에서 사용되는 명령 환경을 사용하고 sh -c싶습니다 .cat

f=test.txt sh -c 'cat "$f"'

파일의 내용을 표시하면 안되나요?

f=test.txt cat $f    

?


참고: 가 무엇인지 묻는 것이 아닙니다 someVariable=someValue command. 왜 첫 번째 예에서는 명령 변수를 사용하고 두 번째 예에서는 사용하지 않는지 묻고 있습니다. 두 번째 예에서 변수 확장이 발생하는 방식은 첫 번째 예에서도 발생해야 합니다.

답변1

일반화하다

작은따옴표 명령 매개변수를 확장하기 전에 f=test.txt sh -c 'cat "$f"'변수 할당이 발생하므로 이 명령은 출력을 생성합니다 . 작은따옴표는 하위 명령이 실행되기 전에 확장이 발생하는 것을 방지합니다.f=test.txt'cat "$f"'cat "$f"

이 명령 f=test.txt cat $f아니요f=test.txt변수 할당이 발생하기 때문에 출력을 생성합니다.뒤쪽에(따옴표 없음) 명령 매개변수 확장 $f.

f=test.txt cat $f출력이 생성되지 않습니까?

f=test.txt cat $f먼저, 예상한 대로 이 명령이 출력을 생성하지 않는 이유를 설명하겠습니다 . 여기서 평가 순서에 대해 약간의 혼란이 있을 수 있습니다.간단한 명령.

f=test.txt명령 본문의 변수 확장(예: $fin 확장 ) cat $f이전에 명령 프롤로그의 변수 할당(예: 할당)이 발생한다고 가정할 수 있습니다 . 그러나 그것은 진실이 아니다. 이를 확인하려면 페이지를 참조하세요.간단한 명령 확장Bash 매뉴얼에서 또는간단한 명령에 대한 섹션내부에POSIX 사양. 두 참조 모두 다음 단락을 포함합니다.

"간단한 명령"은 임의의 순서로 선택적인 변수 할당 및 리디렉션의 시퀀스이며 선택적으로 단어와 리디렉션이 뒤따르고 제어 연산자에 의해 종료됩니다.

주어진 간단한 명령을 실행해야 하는 경우(즉, AND-OR 목록이나사례명령문은 간단한 명령을 우회하지 않습니다.) 명령 텍스트의 처음부터 끝까지 다음 확장, 할당 및 리디렉션을 수행해야 합니다.

  1. 다음 규칙에 따라 변수 할당 또는 리디렉션으로 식별되는 단어쉘 구문 규칙3단계와 4단계의 처리를 위해 저장합니다.

  2. 변수 할당이나 리디렉션이 아닌 단어는 확장되어야 합니다. 확장 후 남은 필드가 있는 경우 첫 번째 필드는 명령 이름으로 처리되어야 하며 나머지 필드는 명령에 대한 인수입니다.

  3. 리디렉션은 다음에 설명된 대로 수행되어야 합니다.리디렉션.

  4. 물결표 확장, 매개변수 확장, 명령 대체, 산술 확장 및 따옴표 제거를 할당하기 전에 모든 변수 할당을 확장해야 합니다.

2단계에서는 명령에서 변수 확장이 발생하지만 1단계에서는 변수 할당이 3단계와 4단계에 저장된다는 점에 유의하세요. 따라서 표현식은 할당이 발생하기 전 cat $f(인수 없이)으로 확장됩니다 . 이는 출력이 나오지 않는 이유를 설명합니다.catf=test.txt

이 주제에 대한 자세한 내용은 다음 게시물을 참조하세요.

f=test.txt sh -c 'cat "$f"' 하다산출물을 생산하다

다음으로 명령이 왜 필요한지 설명하겠습니다.f=test.txt sh -c 'cat "$f"' 하다출력을 생성합니다. 이를 위해 우리는 살펴보아야 합니다.쉘에서 수행되는 일반적인 작업의 전체 목록:

  1. 쉘은 파일에서 입력을 읽습니다(참조:), -c 옵션 또는체계()그리고팝펜()POSIX.1-2008 시스템 인터페이스 볼륨에 정의된 기능입니다. 셸 명령 파일의 첫 번째 줄이 "#!" 문자로 시작하면 결과가 지정되지 않습니다.

  2. 쉘은 입력을 토큰으로 나눕니다. 단어와 연산자를 참조하세요.토큰 인식.

  3. 쉘은 입력을 간단한 명령으로 구문 분석합니다(참조:간단한 명령) 및 복합 명령(참조:복합 명령).

  4. 쉘은 각 명령의 여러 부분에 대해 (별도로) 다양한 확장을 수행하여 명령 및 인수로 처리되는 경로 이름 및 필드 목록을 생성합니다.단어 표현.

  5. 쉘은 리디렉션을 수행합니다(참조리디렉션) 인수 목록에서 리디렉션 연산자와 해당 피연산자를 제거합니다.

  6. 쉘은 함수를 실행합니다(참조:기능 정의 명령), 내장(참조특수 내장 유틸리티), 실행 파일 또는 스크립트(매개변수 이름을 1부터 n까지의 위치 인수로 지정하고 명령 이름(또는 스크립트 내의 함수의 경우 스크립트 이름을 지정)을 0의 위치 인수로 지정합니다(참조).명령어 검색 및 실행).

  7. 쉘은 선택적으로 명령이 완료될 때까지 기다리고 종료 상태를 수집합니다(참조:명령의 종료 상태).

여기에서 함수/내장/실행 가능/스크립트 호출을 볼 수 있습니다(이 목록의 6단계).뒤쪽에간단한 명령을 구문 분석합니다. 그래서 f=test.txt할당이 발생합니다앞으로프로그램 실행 sh -c 'cat "$f"'. 매개변수는 작은따옴표로 묶여 있으므로 구문 분석만 수행됩니다.뒤쪽에명령이 실행됩니다. 따라서 하위 명령은 cat "test.txt".

답변2

쉘 명령에 대한 변수 할당은 명령에 전달된 환경에만 영향을 미치며 쉘이 실행되는 환경에는 영향을 미치지 않습니다.

좀 더 직접적으로 보실 수 있어요

$ f=1
$ f=2 echo $f
1
$

로 설정된 환경에서 실행되지만 echo명령을 빌드하는 데 사용되는 셸 환경이 아닌 명령 환경(빌드 중인)에서 실행되도록 할당됩니다.f2

명령이 없는 할당만 실행 중인 셸 환경에 영향을 미치며, 셸 환경은 명령을 구성하는 데 사용됩니다.

답변3

두 번째 예에서는 $f가 아닌 셸에 의해 확장되기 때문에 셸 환경에 다른 설정이 없다고 cat가정하고 빈 문자열로 확장한 다음 아무것도 없는 것처럼 stdin에서 읽습니다. 주어진 매개변수는 동일합니다.f$fcat

첫 번째 예에서는 $f작은따옴표 안에 있으므로 원래 쉘로 확장되지는 않지만인스턴스 확장을 통해 sh확인cat "$f" 그리고f해당 환경에 설정 되었습니다 .

관련 정보