명령 대체 중에 단어 분리를 비활성화하는 방법은 무엇입니까? 다음은 문제의 간단한 예입니다.
오후 4시 /사용자/paymahn/다운로드 ❯❯❯고양이 테스트.txt 안녕하세요.\n 오후 4시 /사용자/paymahn/다운로드 ❯❯❯ 에코 $(cat test.txt) 안녕하세요 세계 오후 4시 /사용자/paymahn/다운로드 ❯❯❯ echo "$(cat test.txt)" 안녕하세요 세계 오후 4시 1분 /사용자/paymahn/다운로드 ❯❯❯ echo "$(cat "test.txt" )" 안녕하세요 세계
내가 원하는 것은 echo $(cat test.txt)
(또는 명령 대체를 포함한 일부 변형) 출력 입니다 hello\nworld
.
내가 찾은https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html맨 밑에 써있지만 If the substitution appears within double quotes, word splitting and filename expansion are not performed on the results.
도저히 이해가 안가네요. 나는 내가 시도한 예 중 하나가 그 규칙에 맞을 것이라고 생각했지만 그렇지 않은 것 같습니다.
답변1
리터럴을 \n
줄 바꿈으로 변경하는 것은 단어 분리가 아니라 echo
백슬래시를 처리하는 것입니다. 일부 버전은 echo
이를 수행하고 일부는 그렇지 않습니다. Bash는 echo
기본적으로 백슬래시 이스케이프를 처리하지 않지만( -e
플래그나 xpg_echo
옵션 없음) 예를 들어 대시 및 Zsh 버전은 echo
처리합니다.
$ cat test.txt
hello\nworld
$ bash -c 'echo "$(cat test.txt)"'
hello\nworld
$ zsh -c 'echo "$(cat test.txt)"'
hello
world
대신 사용하십시오 printf
:
$ bash -c 'printf "%s\n" "$(cat test.txt)"'
hello\nworld
$ zsh -c 'printf "%s\n" "$(cat test.txt)"'
hello\nworld
또한보십시오:왜 printf가 echo보다 나은가요?
그럼에도 불구하고 sh와 같은 쉘에서 단어 분리기와 와일드카드를 방지하려면 명령 대체 주위에 따옴표를 넣어야 합니다. (sh 모드를 제외하고, zsh는 명령 대체(인수 또는 산술 확장이 아닌) 시에만 토큰화(와일드카드 아님)를 수행합니다.)
답변2
echo의 zsh 구현은 기본적으로 이스케이프 시퀀스를 해석합니다. 가장 간단한 해결책은 다음과 같습니다.
$ echo -E "$(cat test.txt)"
hello\nworld
또는
$ print -r "$(cat test.txt)"
올바른 해결책은 printf를 사용하는 것입니다.
$ printf '%s\n' "$(<test.txt)"