![POSIX 스크립트에서 큰따옴표를 인쇄하는 방법은 무엇입니까?](https://linux55.com/image/211660/POSIX%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C%20%ED%81%B0%EB%94%B0%EC%98%B4%ED%91%9C%EB%A5%BC%20%EC%9D%B8%EC%87%84%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
지금까지 나는 다음을 "\""
사용하여 큰따옴표를 인쇄해 왔습니다.
$ x="abc def"
$ echo "x=\"$x\""
x="abc def"
그러나 이 동작은 정의되지 않은 것 같습니까?
~을 위한echo
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html(XSI 호환 시스템의 추가 사양을 무시하면) 백슬래시는 완전히 정의되지 않은 동작으로 이어집니다.
표준 출력에 기록될 문자열입니다. 첫 번째 피연산자가 -n이거나 피연산자에 <backslash> 문자가 포함된 경우 결과는 구현에 따라 정의됩니다.
이 페이지는printf
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html주로 파일 형식 기호를 나타냅니다.https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html#tag_05이것도 지원되지 않습니다 \"
.
다음 두 가지 방법은 어떻습니까? 명시적으로 POSIX를 준수합니까?
연결
'
과"
문자열$ x="abc def" $ printf x=%s\\n '"'"$x"'"' x="abc def"
8진수 값 사용
"
:$ x="abc def" $ printf x=\\42%s\\42\\n "$x" x="abc def"
대안은 무엇입니까?
답변1
예, 이 동작(사용법 \"
)은 POSIX에서 echo
모든 곳이 아니라 명령에 대해 정의되지 않았습니다. 이것이 echo 대신 printf를 사용하는 이유 중 하나입니다. 읽어주세요왜 printf가 echo보다 나은가요?.
물론 여기에는 몇 가지 설명이 필요합니다.
A \"
는구현 정의그게 경우에만피연산자에코.
여기서 단어 정의는 얼마나 중요합니까? 명령줄에 작성하는 모든 내용은 여러 번 읽고 수정된 다음유틸리티에 피연산자로 제공됨. 우리가 명령줄 인수("단어")라고 부르는 것은 쉘에 의해 여러 가지 방법으로 변환됩니다. 마지막 변경 사항 중 하나는 "인용문 제거"입니다. 결국 이게 결과라면피연산자Contains 는 \"
" echo
올바른" 것으로 간주되는 모든 작업을 수행할 권리가 있습니다.
명령줄이 피연산자와 echo '\"'
OR echo "\\\""
로 연결된 경우 \"
결과는 구현에 따라 정의됩니다.
귀하의 예 x="abc def"; echo "x=\"$x\""
는 다음과 같습니다아니요구현에 따라 정의됩니다. echo에 의해 수신된 피연산자는 입니다 x="abc def"
. 하지만 변수의 내용에 따라 다릅니다 x
.
그러한 것을 방지하려면가능한질문 피연산자가 무엇이든 관계없이 출력이 POSIX로 정의되므로 제한이 없는 printf를 사용해야 합니다.
따라서 큰따옴표를 인쇄하는 일반적인 솔루션은 printf 명령의 형식 부분에 이를 넣는 것입니다.
$ printf 'x="%s"\n' "$x"
x="abc def"
작은 따옴표를 인쇄해야 하는 경우 따옴표를 변경하거나 "따옴표 종료 - 작은 따옴표 넣기 - 따옴표 다시 시작"이라는 일반적인 트릭을 사용해야 합니다.
$ printf 'x='\''%s'\''\n' "$x"
x='abc def'
또는:
$ printf "x='%s'"'\n' "$x"
x='abc def'
또는 더 나은 방법은 작은 따옴표를 큰 따옴표로 묶은 문자열로 전환하는 것입니다.
$ printf 'x=%s\n' "'$x'"
x='abc def'
\ddd
하지만 그렇습니다. printf는 8 진수를 지원하므로 ddd
다음을 사용할 수도 있습니다.
$ printf 'x=\042%s\042\n' "$x"
x="abc def"
위의 모든 솔루션은 유효한 POSIX 구성입니다. 하나를 선택하십시오.
답변2
POSIX 셸에서 다음 명령을 실행해 보세요.
echo "abc"
에 명시된 규칙에 따라2.2.3 큰따옴표, "abc"
은 큰따옴표이므로 큰따옴표 문자는 리터럴이 아니라 큰따옴표로 구성된 묶인 문자입니다. 따라서 첫 번째 인수 값으로 echo
수신하지도 않습니다 ."abc"
abc
또한 2.2.3 큰따옴표의 마지막 단락은 큰따옴표 안에 나타나는 백슬래시의 동작을 정의합니다. "
및 일부 다른 문자의 경우 섹션 2.2에 정의된 "이스케이프 문자로서의 특별한 의미를 유지해야 합니다". . 해당 섹션에 따르면 이스케이프 문자는 "다음 문자의 리터럴 값"을 유지합니다.
이는 원래 질문을 제기한 원래 질문 텍스트의 첫 번째 예가 완벽하게 괜찮다는 것을 의미합니다.
$ x="abc def"
$ echo "x=\"$x\""
x="abc def"
echo
POSIX 쉘은 이미 백슬래시 문자를 이스케이프 문자로 사용하기 때문에 프로그램은 백슬래시 문자를 전혀 수신하지 않습니다 . 따라서 백슬래시가 매개변수 값에 나타나면 백슬래시가 없기 때문에 echo
사양(또는 다른 프로그램)이 정의하는 내용은 중요하지 않습니다 .printf
물론 위의 내용은 모두 제한적이며 x
위에서 설정한 값(및 기타 일부 제한된 값)에만 유효합니다. 값을 x
다른 것으로 변경할 수 있는 경우 따옴표를 제거한 후 백슬래시를 포함할 수 있습니다 \
. 이는 셸 명령줄 인수(셸 용어로 "단어")를 다음으로 변환합니다.피연산자존재하다유틸리티에 대한 POSIX의 말.
이로 인해 다음 내용이 echo
구현 정의될 위험이 있습니다. printf
그런 문제는 없습니다.