tr "\'\\\"\?\!" "01234" 명령이 작동하지 않는 이유는 무엇입니까?

tr "\'\\\"\?\!" "01234" 명령이 작동하지 않는 이유는 무엇입니까?

터미널에서 다음과 같이 일부 변수 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 - 안에 포함된 문자열을 가져오려면 백슬래시를 이스케이프 처리해야 문자 그대로의 백슬래시로 처리하고 후속 이스케이프가 아님을 알 수 있다는 것입니다.''\''trtr"

관련 정보