이것은 bash에서 여러 줄 명령으로 기록됩니다.

이것은 bash에서 여러 줄 명령으로 기록됩니다.

여기에서 문서를 테스트하기 위해 스니펫을 만들었습니다.

$ cat test101.sh
ls
$ bash test101.sh
bmdt.md       brmdh.md  fild.md  test     test101.sh  test2  test5  testfile
breakfast.md  exec  file.md  test.sh  test12      test3  test7

여기에 온다 문서

$ $(cat << EOF
→ ls
→ EOF)
bmdt.md       brmdh.md  fild.md  test     test101.sh  test2  test5  testfile
breakfast.md  exec  file.md  test.sh  test12      test3  test7

잘 작동
하지만 불행히도 구조화된 명령의 경우에는 그렇지 않습니다.

$ $(cat << EOF
→ for i in *
→ do 
→   stat $i
→ done
→ EOF)
-bash: for: command not found

나는 전에 시도했다

$ bash $(cat << EOF
→ for i in *
→ do
→   stat $i
→ done
→ EOF)
bash: for: No such file or directory

for 명령이 작동하지 않는 문제는 무엇입니까?

답변1

여기서 문서화는 리디렉션의 한 형태입니다. 명령에서 cat해당 명령으로 리디렉션한 다음 출력을 명령 대체 명령으로 사용하려고 합니다.

  1. $i이 문서는 내용이 구체화되면 확장될 것입니다. 이는 문서의 루프가 실제로 실행되기 훨씬 전에 발생합니다. i변수가 설정되지 않은 경우 빈 문자열로 확장됩니다. 확장이 수행되지 않도록 이 문서를 인용하거나 (첫 번째 항목 EOF'EOF'또는 로 인용하여) 확장을 방지하기 위해 명시 적으로 이스케이프 하도록 선택할 수 있습니다 .\EOF$\$
  2. 여기 문서의 내용은 줄 바꿈으로 구분된 단일 문자열로 해석됩니다. 일반적인 토큰 인식 및 일반 명령 구문 분석과 관련된 기타 단계를 거치지 않지만 명령 대체가 인용되지 않았기 때문에 별도의 단어로 분할됩니다. 특히 for쉘 키워드로 인식되지 않습니다. 이것이 첫 번째 실패한 예가 실패한 이유입니다. 문자열을 재평가하려면 eval이를 수행해야 합니다. 그러면 문자열이 명령줄에 주어졌을 때 쉘이 하는 것처럼 문자열을 재평가하게 됩니다.
  3. 마지막 예는 bash많은 단어가 이어지도록 확장됩니다. 첫 번째 단어는 현재 디렉토리에서 호출되는 쉘 스크립트를 실행할 것으로 예상 for하지만 그렇게 하지 못합니다.bashfor

  4. 모든 예에서,bash ~해야 한다또한 여기 문서가 적절하게 종료되지 않는다고 불평합니다(마지막 줄에 EOF)닫는 괄호가 있기 때문에 EOF).

    bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')
    

    bashmacOS의 기본 버전과 같은 이전 버전을 사용하지 않는 한 .

대신, 이는 코드를 재해석해야 하는 문자열로 변환하는 것을 방지하고 대신 실행을 위해 쉘 인터프리터에 직접 인라인 쉘 스크립트로 문서를 제공하므로 더 나은 작업 선택이 될 것입니다.

bash <<'END_SCRIPT'
for i in *; do
    printf 'Filename: "%s"\n' "$i"
done
END_SCRIPT

첫 번째 예는 간단한 명령이기 때문에 작동합니다.

관련 정보