터미널에서 다음과 같이 일부 변수 char을 정의하면:
export char=\'\\\"\?\!
실제로 char은 문자열입니다.
'\"?!
그런 다음 숫자로 tr
바꾸기 명령을 사용합니다.'\"?!
01234
tr "\'\\\"\?\!" "01234"
나는 내가 얻을 것이라고 생각했다
01234
대신 나는 얻는다
0\123
누군가 나에게 무슨 일이 일어나고 있는지 설명해 줄 수 있다면 매우 감사할 것입니다.
sed
각 문자를 개별적으로 명령으로 바꾸면 이 문제를 피할 수 있는 것 같지만 그 이유는 무엇입니까?
답변1
셸뿐만 아니라 tr
자체적으로 백슬래시를 특수 이스케이프 문자로 해석합니다. 자세한 내용은 해당 설명서를 참조하세요. 따라서 백슬래시를 바꾸려면 tr
리터럴(백슬래시 2개)을 받았는지 확인해야 합니다. \\
예를 들어 이 작업은 셸에서 수행할 수 있으며 char=...\\\\...
, 셸에서 백슬래시를 처리하는 방법을 올바르게 이해했으므로 이 부분에서는 추가 설명이 필요하지 않습니다.
이는 사용자에게는 불편할 수 있지만 다른 많은 경우에는 편리하며 문자 세트 또는 NUL 바이트를 검색 또는 대체 세트의 일부로 허용합니다(그렇지 않으면 불가능함). 예를 들어 NUL로 구분된 문자열을 줄 바꿈으로 구분된 문자열로 변환하려면 유사한 작업을 수행 tr '\0' '\n' < /proc/1234/environ
하거나 소문자 문자열을 사용할 수 있습니다 tr '[:upper:]' '[:lower:]'
. tr
이스케이프 문자 없이는 이 중 어느 것도 불가능합니다 .
답변2
문자열과 스크립트를 항상 작은따옴표( '
)로 묶으십시오.필요"
쉘이 이를 해석하도록 하려면 큰따옴표( )를 사용하십시오 . 바라보다https://mywiki.wooledge.org/Quotes. 큰따옴표를 사용하면 쉘을 초대하여 "이스케이프" 지옥에 빠지게 됩니다. 문자열의 문자를 이스케이프하여 쉘이 먼저 해당 문자를 모두 사용한 다음 도구가 사용할 수 있도록 다시 이스케이프해야 합니다. 1개의 레이어 대신 여러 개의 이스케이프 레이어를 추가해야 합니다. 이렇게 하지 말고 대신 작은따옴표를 사용하세요.
$ printf '%s\n' ''\''\"?!'
'\"?!
$ printf '%s\n' ''\''\"?!' | tr ''\''\\"?!' '01234'
01234
변수를 정의할 때도 마찬가지입니다 char
. 모든 백슬래시를 사용하는 대신:
export char=\'\\\"\?\!
문자열을 올바르게 작은따옴표로 묶으세요.
$ export char=''\''\"?!'
$ printf '%s\n' "$char"
'\"?!
$ printf '%s\n' "$char" | tr ''\''\\"?!' '01234'
01234
위에서 알아야 할 것은 '
셸에서 a - 안에 포함된 문자열을 가져오려면 백슬래시를 이스케이프 처리해야 문자 그대로의 백슬래시로 처리하고 후속 이스케이프가 아님을 알 수 있다는 것입니다.'
'\''
tr
tr
"