몇 가지 비슷한 주제를 본 적이 있지만 변수를 인용하지 않는다는 내용이 있는데, 이는 원치 않는 결과를 초래할 수 있다는 것을 알고 있습니다.
이 코드를 보고 다음 코드 줄이 실행될 때 실행할 무언가를 삽입할 수 있는지 궁금합니다.
echo run after_bundle
답변1
위에 추가 메모를 추가하세요.@Kusalananda의 훌륭한 답변.
echo run after_bundle
문제 없습니다. 이 세 매개변수의 어떤 문자도 echo
쉘 특정 문자를 포함하도록 전달되지 않기 때문입니다.
그리고 (여기서 추가로 언급하고 싶은 점은) 이러한 바이트를 쉘 특정 문자로 변환할 수 있는 시스템 로케일이 없습니다.
이 문자들은 모두 무엇입니까?POSIX 호출휴대용 문자 세트. 이러한 문자는 POSIX 시스템의 모든 문자 집합에서 동일한 방식으로 나타나고 인코딩되어야 합니다.
따라서 명령줄은 로케일에 관계없이 동일하게 해석됩니다.
이제 이 이식 가능한 문자 집합 외부의 문자를 사용하기 시작하면 해당 문자가 셸에 특별하지 않더라도 해당 문자를 인용하는 것이 좋습니다. 왜냐하면 다른 로케일에서는 해당 문자를 구성하는 바이트가 다른 문자로 해석될 수 있기 때문입니다. 쉘 스페셜이 됩니다. 명령을 사용하든 echo
다른 명령을 사용하든 문제는 echo
셸이 코드를 구문 분석하는 방식이 아닙니다.
예를 들어 UTF-8에서는 다음과 같습니다.
echo voilà | iconv -f UTF-8 -t //TRANSLIT
인코딩은 à
0xc3 0xa0입니다. 이제 쉘 스크립트에 해당 코드 줄이 있고 문자 세트가 UTF-8이 아닌 로케일을 사용하는 사용자가 쉘 스크립트를 호출하는 경우 이 두 바이트는 매우 다른 문자를 생성할 수 있습니다.
예를 들어, fr_FR.ISO8859-15
로케일에서 일반적인 프랑스어 로케일은 프랑스어를 포함하는 표준 단일 바이트 문자 세트(영어를 포함한 대부분의 서유럽 언어와 동일)를 사용하며 0xc3 바이트는 문자로 해석되고 Ã
0xa0은 문자로 해석됩니다. 비문자 집합 . 공백 문자를 끊습니다.
NetBSD³와 같은 일부 시스템에서는 잘림 방지 공백이 다음과 같이 처리됩니다.공백문자( isblank()
true를 반환하고 일치함 )이므로 [[:blank:]]
쉘과 마찬가지로 bash
구문에서 토큰 구분 기호로 처리됩니다 .
echo
이는 as 인수로 실행 하는 대신 $'voil\xc3\xa0'
as 인수로 실행 중이므로 올바르게 인쇄 $'voil\xc3'
되지 않음을 의미합니다 voilà
.
BIG5, BIG5-HKSCS, GB18030, GBK와 같은 중국어 문자 세트의 경우 상황은 더욱 악화됩니다. 이 문자 세트에는 인코딩에 |
, `
, \
(최악의 예를 들자면) 문자가 포함된 문자가 많이 있습니다. ¥
은 아니지만 0x5c로 인코딩되어 있기 때문에 대부분의 도구에서는 \
여전히 그렇게 처리됩니다 .\
예를 들어, 중국어 로케일을 사용하는 경우 zh_CN.gb18030
다음과 같은 스크립트를 작성할 수 있습니다.
echo 詜 reboot
스크립트는 詜 reboot
GB18030 또는 GBK를 사용하는 로케일, 唰 reboot
BIG5 또는 BIG5-HKSCS를 사용하는 로케일, ASCII를 사용하는 C 로케일 또는 ISO8859-15 또는 UTF-8을 사용하는 로케일로 reboot
출력 됩니다. GB18030 인코딩은 詜
0xd4 0x7c이고 0x7c는 ASCII 인코딩이므로 다음을 |
실행하게 됩니다.
echo �| reboot
(그러나 �는 로케일에서 렌더링된 0xd4 바이트를 나타냅니다.) 덜 해로운 uname
대안을 사용하는 예 reboot
:
$ echo $'echo \u8a5c uname' | iconv -t gb18030 > myscript
$ LC_ALL=zh_CN.gb18030 bash ./myscript | sed -n l
\324| uname$
$ LC_ALL=C bash ./myscript | sed -n l
Linux$
( uname
이미 실행 중).
따라서 내 제안은 이식 가능한 문자 집합 외부의 문자가 포함된 모든 문자열을 인용하는 것입니다.
\
그러나 and의 인코딩은 이러한 문자 중 일부의 인코딩에서 발견되므로 or ( and /or는 여전히 특별함) 을 사용하지 않고 이식 가능한 문자 집합 외부의 문자를 참조하는 `
것이 좋습니다 .\
"..."
$'...'
`
\
'...'
'
나는 로케일의 문자 세트 에 인코딩이 포함된 문자(물론 자체 제외)가 있는 시스템을 알지 못하므로 '
이것이 '...'
가장 안전할 것입니다.
일부 쉘은 $'\uXXXX'
유니코드 코드 포인트를 기반으로 한 문자 표현도 지원합니다. zsh
Windows 및 Windows와 같은 셸 에서는 bash
문자가 로케일의 문자 집합 인코딩에 삽입됩니다. 그러나 문자 집합에 해당 문자가 없으면 예기치 않은 동작이 발생할 수 있습니다. 이를 통해 쉘 코드에 ASCII가 아닌 문자를 삽입하는 것을 방지할 수 있습니다.
따라서 위의 내용은 다음과 같습니다.
echo 'voilà' | iconv -f UTF-8 -t //TRANSLIT
echo '詜 reboot'
또는:
echo $'voil\u00e0'
echo $'\u8a5c reboot'
(이러한 문자가 없는 로케일에서 실행하면 스크립트가 중단될 수 있습니다.)
아니면 더 나은 이유는 \
( echo
또는 적어도일부 echo
구현, 최소한 Unix 호환 구현):
printf '%s\n' 'voilà' | iconv -f UTF-8 -t //TRANSLIT
printf '%s\n' '詜 reboot'
( \
첫 번째 인수도 특별하므로 printf
인코딩이 포함될 수 있는 경우 ASCII가 아닌 문자를 피하는 것이 가장 좋습니다 \
.)
다음 작업도 수행할 수 있습니다.
'echo' 'voilà' | 'iconv' '-f' 'UTF-8' '-t' '//TRANSLIT'
(이것은 약간 과잉이지만 휴대용 문자 세트에 어떤 문자가 있는지 확실하지 않은 경우 마음을 편하게 할 수 있습니다)
또한 고대 `...`
형태의 명령 대체(다른 수준의 백슬래시 처리를 도입함)를 절대 사용하지 말고 $(...)
대신 이를 사용하십시오.
1은 기술적으로 유틸리티 echo
에 인수로 전달되며 (호출 방법을 알려줌) , 3은 오늘날 대부분의 쉘에 내장되어 있으므로 3개의 인수 목록이 있는 파일의 에뮬레이션은 쉘에서 수행됩니다. 인수 목록은 명령이 주로 작동하는 인수이기 때문에 두 번째 인수( to )로 시작하는 것으로 생각하는 것이 일반적입니다.echo
argv[0]
argc
echo
exec()
/bin/echo
argv[1]
argv[argc - 1]
² 주목할만한 예외 중 하나는 문자 세트에 Nor 문자 ja_JP.SJIS
가 없는 FreeBSD 시스템의 터무니없는 로케일 입니다 !\
~
³ 많은 시스템(FreeBSD, Solaris, GNU 시스템 제외)이 U+00A0을 [[:blank:]]
UTF-8 로케일로 처리하는 반면, 다른 로케일(예: ISO8859-15를 사용하는 시스템)에서는 그렇게 하는 시스템이 거의 없습니다. 그런 문제.
답변2
특정 상황을 타겟팅
echo run after_bundle
인용은 필요하지 않습니다. 매개변수 echo
는 정적 문자열이고 변수 확장이나 명령 대체 등을 포함하지 않으므로 따옴표가 필요하지 않습니다. 그것은 "단지 두 단어"입니다.스티븐은 지적했다., 그들은 추가로 구성됩니다휴대용 문자 세트).
"위험"은 쉘이 확장하거나 해석할 수 있는 변수 데이터를 처리할 때 발생합니다. 이 경우 셸이 올바른 작업을 수행하고 결과가 예상대로 나오도록 주의해야 합니다.
다음 두 질문에는 관련 정보가 포함되어 있습니다.
echo
때때로 이 사이트의 답변에서 잠재적으로 유해한 명령을 "보호"하는 데 사용됩니다. 예를 들어 다음을 사용하여 파일을 삭제하거나 파일을 새 대상으로 이동하는 방법을 보여줄 수 있습니다.
echo rm "${name##*/}.txt"
또는
echo mv "$name" "/new_dir/$newname"
실제로 파일을 삭제하거나 이름을 바꾸는 대신 터미널에 명령이 출력됩니다. 그런 다음 사용자는 명령을 확인하고 괜찮아 보이는지 확인한 후 삭제 echo
하고 다시 실행할 수 있습니다.
명령은 echo run after_bundle
사용자에게 지시하는 것일 수도 있고, 결과를 알지 못한 채 실행하기에는 너무 위험한 "주석 처리된" 코드일 수도 있습니다.
이러한 방식으로 사용될 때 echo
수정된 명령이 무엇을 하는지 알아야 하며 수정된 명령이 실제로 수행되는지 확인해야 합니다.예안전하다(이럴 수도 있다아니요리디렉션이 포함되어 있고 파이프에서 사용하면 작동하지 않습니다.)