'eval'은 다음 명령의 리디렉션된 부분에 셸을 적용합니까?

'eval'은 다음 명령의 리디렉션된 부분에 셸을 적용합니까?

eval명령 과 함께 사용하면 eval명령의 리디렉션 부분에 쉘이 두 번 적용됩니까?

리디렉션의 파일 이름에 공백이 포함되어 있다고 가정할 때 eval모든 구문 분석, 셸 확장 및 토큰화 단계가 여러 번 적용되면 파일 이름은 두 번째 토큰화 단계에서 두 단어로 분할됩니다.

eval다음 예는 다음 명령의 리디렉션 부분에 셸이 두 번 적용되지 않으므로 파일 이름이 두 단어로 분할되지 않는다는 의미입니까 ?

$ filename="my file"
$ eval "cat" < "$filename"
hi

답변1

제공한 예에서 유일한 것은 eval리디렉션 cat이 외부에서 발생 eval하고 파일이 명령의 표준 입력으로 제공된다는 것입니다 eval "cat".

한 가지 변형은 작은따옴표를 사용하여 리디렉션을 포함하여 전체 명령을 인용하는 것입니다.

$ eval 'cat < "$filename"'
hi

이제 eval리디렉션 및 변수 이름을 포함한 전체 문자열을 가져오므로 변수 확장은 물론 공백이 포함된 필수 파일 이름 참조도 수행됩니다. 이것은 여전히 ​​작동합니다.

또 다른 옵션은 문자열에 큰따옴표를 사용하는 것입니다.

$ eval "cat < '$filename'"
hi

이제 변수는 셸에 의해 확장되지만 변수 안의 따옴표가 파일 이름을 함께 유지하기 때문에 여전히 작동합니다. (파일 이름에 아포스트로피가 포함되어 있으면 깨질 수 있습니다.)

"작동하지 않는 것"은 다음과 같습니다.

$ eval "cat" "<" "$filename"

이는 귀하의 예와 유사하지만 따옴표를 사용하면 <외부 쉘이 리디렉션을 수행하지 않습니다. eval그런 다음 매개변수를 함께 넣으면 결과 명령은 다음과 같습니다.

cat < my file

my file이제 주변 따옴표가 사라졌기 때문에 예상대로 작동하지 않습니다 .

답변2

작동 방식은 eval실행할 셸 명령에 매개 변수를 함께 구성하는 것입니다. 변수 이후filename 인용되면 단어 분할이 수행되지 않습니다.언제이것명령은 실행되도록 작성되었습니다.

파일 이름에 공백이 있으면 동일하게 적용되지 않을 수 있으며 따옴표 없이 확장하면 오류가 발생합니다. 예를 들어

filname=my\ file
echo "dude" > my\ file
eval cat < $filename
bash: $filename: ambiguous redirect

여기서 수행된 토큰화와 cat입력 리디렉션에 대해 잘못된 파일 이름을 수신하여 오류가 발생했다는 점에 유의하세요.

또한 리디렉션 없이 사용하거나 cat파일에서 직접 사용하는 경우 이 경우 eval두 개의 파일이 열립니다.cat

eval cat $filename

달리기로 전환됩니다

cat my file

예를 들어, 지정된 파일이 현재 디렉터리에 있으면 해당 내용을 표시하고 지정된 file파일이 존재하지 않는다는 오류 스트림을 표시합니다.my

filename=my\ file
echo "foo" > file

my파일을 존재하지 않게 만들고 있습니다.

eval cat $filename 2>&1
cat: my: No such file or directory
foo

관련 정보