이 예의 인용 제거 단계에서 bash가 백슬래시를 제거하지 않는 이유는 무엇입니까?

이 예의 인용 제거 단계에서 bash가 백슬래시를 제거하지 않는 이유는 무엇입니까?

배쉬에서

$ va='\\abc'
$ echo $va
\\abc

할당에서 va='\\abc'작은따옴표는 값의 두 개의 백슬래시를 유지합니다 va.

echo 명령에서 bash는 먼저 매개변수를 확장(확장)한 다음 매개변수 확장 결과에서 따옴표를 제거합니다. echo $va이것이 맞습니까? 따옴표를 제거하면 백슬래시와 따옴표가 제거되는데 왜 두 개의 백슬래시가 남아 있습니까? 나는 결과가 다음과 같을 것으로 예상했습니다. 비교를 위해$va\\abc\abc

$ echo \\abc
\abc

Bash 매뉴얼에서 뭔가를 놓쳤습니까? 내가 누락 된 부분을 지적해 주시면 감사하겠습니다.

감사해요.

답변1

더 간단한 비교로 시작해보세요:

$ echo '\\abc'
\\abc
$ echo \\abc
\abc

echo첫 번째 명령에서 아포스트로피는 이미 인용에 사용되었으므로 매개변수의 일부가 아닙니다 . 두 개의 백슬래시를 포함하여 내부의 모든 문자가 로 전달됩니다 echo.

두 번째 명령에서 첫 번째 백슬래시는 두 번째 백슬래시를 나타냅니다. 인용에 사용된 내용은 주장의 일부를 구성하지 않습니다 echo. 다른 하나는 echo, 및 abc(따옴표가 없지만 메타 문자가 아니기 때문에 중요하지 않습니다)로 전달됩니다.

이제 명령 순서에 대해 논의할 준비가 되었습니다.

$ va='\\abc'
$ echo $va
\\abc

할당 명령이 실행될 때 아포스트로피는 그 사이의 모든 것을 나타냅니다. 아포스트로피는 할당된 값의 일부가 아니지만 두 개의 백슬래시를 포함한 다른 모든 값의 일부가 됩니다.

명령 에는 echo따옴표가 없습니다. va값을 검색하여 매개변수 목록에 삽입합니다. 이제 2개의 백슬래시를 포함하는 매개변수가 있지만 따옴표 문자를 찾는 구문 분석 단계가 변수 확장 전에 완료되므로 따옴표 문자로 사용할 수 없습니다.

변수 확장은 매크로 확장과 다릅니다. 결과 인수 목록은 전체 명령줄 구문 분석기에 피드백되지 않습니다. 일부 사후 처리(단어 분리 및 와일드카드)가 수행되었지만 두 번째 따옴표 제거 및 변수 확장은 수행되지 않았습니다.

인수 목록을 작성하고 사용 가능한 모든 쉘 기능을 사용하여 전체 내용을 새 명령줄로 다시 구문 분석하려는 경우 이 방법을 사용할 수 있습니다 eval. "모든 쉘 기능"이 많기 때문에 이는 일반적으로 나쁜 생각입니다. 조심하지 않으면 나쁜 일이 일어날 수 있습니다.

$ va='\\abc'
$ eval echo $va
\abc

완벽해요, 그렇죠?

$ va='\\abc;rm -rf $important_database'
$ eval echo $va
\abc
^C^C^C ARGH!

쉘 변수의 값에 쉘 인용 구문을 사용하고 싶다면 문제 해결을 위한 다른 접근 방식을 생각해 보십시오.

답변2

Bash 매뉴얼에서 뭔가를 놓쳤습니까?

예.매뉴얼에서:

\이전 확장 이후에는 위의 확장 중 하나에서 생성되지 않은 ' ', ' ' 및 ' ' 문자의 인용되지 않은 모든 항목이 '제거됩니다."

여기서 "이전 확장"과 "상위 확장"은 매개변수(변수) 확장, 명령어 대체 등을 의미합니다.

답변3

대답은 간단합니다. 한 줄입니다.

echo $va

제거해야 하는 따옴표가 포함되어 있지 않습니다.

이는 40년 넘게 쉘의 정의였습니다. Bourne Shell은 1976년 AT&T에서 처음 등장했습니다.

참고: 이 맥락에서 "참조"는 1970년대 8비트 개방형 문자를 의미합니다. 이것이 쉘의 내부 인용 형식입니다.

Bourne Shell이 ​​8비트 문자를 지원하도록 재설계됨에 따라 이러한 형태의 내부 인용은 1980년대 중반에 내부 문자열에서 인용된 문자 앞에 백슬래시로 대체되었습니다.

현재 Bourne Shell은 다음과 같이 작동합니다.

  • 작은따옴표로 작성된 문자열은 백슬래시로 대체됩니다. 예를 들어, 이는 'abc'가 \a\b\c로 대체됨을 의미합니다.

  • 명시적인 유형의 백슬래시가 있는 문자열은 내부적으로 유지됩니다.

  • 큰따옴표로 묶인 문자열은 큰따옴표를 유지하므로 "abc"는 내부적으로 "abc"로 유지됩니다.

인수 확장을 수행할 때 쉘은 모든 유형의 인용 문자열(위의 세 가지 형식 참조)을 문자 앞에 단일 백슬래시가 앞에 오는 형식으로 대체합니다. 이는 "인용 제거"를 수행할 때 제거됩니다.

그런데: 변수 확장:

abc=123

완성된

command "$abc"

밝혀지다

command \1\2\3

견적 삭제를 완료하기 전.

command $abc

밝혀지다

command 123

견적 삭제를 완료하기 전.

관련 정보