에코가 인용 문자를 무시하는 이유는 무엇입니까?

에코가 인용 문자를 무시하는 이유는 무엇입니까?

명령 echo에 내가 제공한 전체 텍스트가 포함되어 있지 않습니다. 예를 들어, 이렇게 하면:

   $ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '

다음과 같이 출력됩니다.

echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print } `

내 echo 명령의 작은따옴표( )는 '포함되지 않습니다. 큰따옴표로 전환하면 다음과 같습니다.

$ echo " echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `  "

echo전혀 아무것도 출력하지 않습니다! 첫 번째 예에서는 작은따옴표를 생략하고 두 번째 예에서는 아무것도 출력하지 않는 이유는 무엇입니까? 입력한 내용을 정확하게 출력하려면 어떻게 해야 합니까?

답변1

귀하의 쉘은 '및 를 포함한 따옴표 "가 도착하기도 전에 해석하고 있습니다 echo. 나는 대개 내 주장이 불필요하더라도 응답으로 큰따옴표를 사용합니다.

$ echo "Hello world"
Hello world

따라서 첫 번째 예에서 출력에 문자 그대로 따옴표를 포함하려면 이를 이스케이프 처리해야 합니다.

$ echo \'Hello world\'
'Hello world'

또는 이미 따옴표로 묶인 매개변수에 사용해야 합니다(그러나 동일한 종류의 따옴표는 아닙니다. 그렇지 않으면 어쨌든 이스케이프해야 합니다).

$ echo "'Hello world'"
'Hello world'

$ echo '"Hello world"'
"Hello world"

두 번째 예에서는 문자열 중간에 명령 대체를 실행합니다.

grep  $ARG  /var/tmp/setfile  | awk {print $2}

로 시작하는 것들도 $셸에 의해 독점적으로 처리됩니다. 즉, 셸은 이를 변수로 취급하고 해당 값으로 바꿉니다. 이러한 변수 중 어느 것도 쉘에 설정되지 않았을 가능성이 높으므로 실제로는 실행됩니다.

grep /var/tmp/setfile | awk {print}

하나의 인수만 보기 때문에 grep인수가 검색 중인 패턴이고 데이터를 읽어야 하는 위치가 stdin이라고 가정하므로 입력을 기다리는 것을 차단합니다. 그래서 두 번째 명령이 중단된 것 같습니다.

인수를 작은따옴표로 묶으면 이런 일이 발생하지 않으므로(이것이 첫 번째 예제가 거의 성공하는 이유입니다) 원하는 출력을 얻는 한 가지 방법은 다음과 같습니다.

echo \'' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '\'

큰따옴표로 묶을 수도 있지만 s를 이스케이프하여 $쉘이 이를 변수로 구문 분석하지 않도록 해야 하며 백틱을 이스케이프하여 쉘이 명령 대체를 즉시 실행하지 않도록 해야 합니다.

echo "' echo PARAM=\`  grep  \$ARG  /var/tmp/setfile  | awk '{print \$2}' \`    '"

답변2

나는 당신의 시도가 왜 그렇게 되었는지 자세히 설명하지 않을 것입니다.마이클 모로젝의 답변이것을 아주 잘 다룹니다. 즉, 작은따옴표( ) '…'사이의 모든 내용은 문자 그대로(특히 '리터럴 문자열의 끝을 표시하는 첫 번째 인용) 해석되는 반면, `ands $는 특별한 의미를 유지합니다 "…".

작은 따옴표 안에는 따옴표가 없으므로 작은 따옴표로 묶인 문자열 안에 작은 따옴표를 넣을 수 없습니다. 그러나 다음과 같은 관용구가 있습니다.

echo 'foo'\''bar'

foo'bar이는 인수가 echo작은따옴표로 묶인 3문자 문자열로 구성되고 foo, 단일 문자로 연결되고(특수한 의미로부터 문자를 보호하기 위해 선행하여 얻음 ') 작은따옴표로 묶인 3문자 문자열로 연결되기 때문에 인쇄됩니다 . 따라서 이것이 정확히 뒤에서 무슨 일이 일어나고 있는지는 아니지만 작은따옴표로 묶인 문자열 내에 작은따옴표를 포함하는 방법으로 생각할 수 있습니다.'\bar'\''

복잡한 여러 줄 문자열을 인쇄하려면 더 나은 도구는 다음과 같습니다.여기 문서. 여기서 문서는 두 개의 문자 <<, 그 뒤에 태그(예를 들어) <<EOF, 몇 줄의 텍스트, 마지막으로 해당 줄에 있는 별도의 닫는 태그로 구성됩니다. 마크가 어떤 방식으로든 인용된 경우( 'EOF'또는 "EOF"또는 'E""OF' 또는 ...) 텍스트는 문자 그대로 해석됩니다(even 이 일반 문자인 경우를 \EOF제외하고 작은 따옴표 안의 것처럼 ). '토큰이 전혀 인용되지 않으면 텍스트는 큰따옴표로 묶인 문자열처럼 해석되어 $\`특별한 상태를 유지합니다(그러나 "개행 문자는 문자 그대로 해석됩니다).

cat <<'EOF'
echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `
EOF

답변3

좋아요, 이렇게 하면 됩니다:-

echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '

여기에서 테스트해보세요:-

[asmith@yagi ~]$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '
 echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' ` 

답변4

우리가 당신의 입찰을 수행하자

$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '

먼저 따옴표 없는 공백을 구분 기호로 사용하여 단어로 분할합니다.

Arg[1]=“' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print”
Arg[2]=“$2}' `    '”

다음으로 매개변수 확장을 수행합니다. 확장 $…하지만 내부적으로는 확장하지 않습니다 '…'. 는 비어 있기 때문에 $2(예를 들어 설정하지 않는 한 set -- …) 빈 문자열로 대체됩니다.

Arg[1]=“' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print”
Arg[2]=“}' `    '”

다음으로 따옴표를 제거하십시오.

Arg[1]=“ echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print”
Arg[2]=“} `    ”

그런 다음 이러한 인수는 echo로 전달되어 공백으로 구분하여 하나씩 인쇄합니다.

“ echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print } `    ”

이 단계별 설명을 통해 관찰된 동작이 더 명확해지기를 바랍니다. 이 문제를 방지하려면 다음과 같이 작은따옴표를 이스케이프 처리하세요.

$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '

그러면 작은따옴표 문자열이 끝나고 단어에 (이스케이프 처리된) 작은따옴표가 추가된 다음 단어를 분할하지 않고 새 작은따옴표 문자열이 시작됩니다.

관련 정보