![이것은 bash에서 여러 줄 명령으로 기록됩니다.](https://linux55.com/image/141226/%EC%9D%B4%EA%B2%83%EC%9D%80%20bash%EC%97%90%EC%84%9C%20%EC%97%AC%EB%9F%AC%20%EC%A4%84%20%EB%AA%85%EB%A0%B9%EC%9C%BC%EB%A1%9C%20%EA%B8%B0%EB%A1%9D%EB%90%A9%EB%8B%88%EB%8B%A4..png)
여기에서 문서를 테스트하기 위해 스니펫을 만들었습니다.
$ 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
해당 명령으로 리디렉션한 다음 출력을 명령 대체 명령으로 사용하려고 합니다.
$i
이 문서는 내용이 구체화되면 확장될 것입니다. 이는 문서의 루프가 실제로 실행되기 훨씬 전에 발생합니다.i
변수가 설정되지 않은 경우 빈 문자열로 확장됩니다. 확장이 수행되지 않도록 이 문서를 인용하거나 (첫 번째 항목EOF
을'EOF'
또는 로 인용하여) 확장을 방지하기 위해 명시 적으로 이스케이프 하도록 선택할 수 있습니다 .\EOF
$
\$
- 여기 문서의 내용은 줄 바꿈으로 구분된 단일 문자열로 해석됩니다. 일반적인 토큰 인식 및 일반 명령 구문 분석과 관련된 기타 단계를 거치지 않지만 명령 대체가 인용되지 않았기 때문에 별도의 단어로 분할됩니다. 특히
for
쉘 키워드로 인식되지 않습니다. 이것이 첫 번째 실패한 예가 실패한 이유입니다. 문자열을 재평가하려면eval
이를 수행해야 합니다. 그러면 문자열이 명령줄에 주어졌을 때 쉘이 하는 것처럼 문자열을 재평가하게 됩니다. 마지막 예는
bash
많은 단어가 이어지도록 확장됩니다. 첫 번째 단어는 현재 디렉토리에서 호출되는 쉘 스크립트를 실행할 것으로 예상for
하지만 그렇게 하지 못합니다.bash
for
모든 예에서,
bash
~해야 한다또한 여기 문서가 적절하게 종료되지 않는다고 불평합니다(마지막 줄에EOF)
닫는 괄호가 있기 때문에EOF
).bash: warning: here-document at line 1 delimited by end-of-file (wanted `EOF')
bash
macOS의 기본 버전과 같은 이전 버전을 사용하지 않는 한 .
대신, 이는 코드를 재해석해야 하는 문자열로 변환하는 것을 방지하고 대신 실행을 위해 쉘 인터프리터에 직접 인라인 쉘 스크립트로 문서를 제공하므로 더 나은 작업 선택이 될 것입니다.
bash <<'END_SCRIPT'
for i in *; do
printf 'Filename: "%s"\n' "$i"
done
END_SCRIPT
첫 번째 예는 간단한 명령이기 때문에 작동합니다.