에코가 내 인용 부호를 무시하는 이유는 무엇입니까?


24

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


3
여기서 달성하려는 것이 확실하지 않습니다. 하나의 반향 문을 다른 반점에 중첩시키는 이유는 무엇입니까? 아니면 문자 그대로 명령을 인쇄하려고합니까 (예를 들어 등)?
— Andy Smith

에코 출력을 다른 파일에 삽입해야합니다

당신이하려는 일을 설명해야합니다. "다음 텍스트를 추가하고 싶습니다 : '…'파일에."
— MikeyB

2
5 분 동안 이것을 편집하려고했지만 원하는 출력이 무엇인지 진지하게 알지 못합니다. 편집 : 좋아, 나는 지금 추측이 있다고 생각하므로 편집을 시도했다. 그것이 당신이 의도 한 것이 아니라면
— Michael Mrozek

1
@Michael-와우-내가 당신에게 당신의 편집에 대한 몇 가지 담당자를 줄 수 있다면, 나는 정말 좋은 질문이 될 것입니다!
— 랜달

답변:


33

당신의 쉘은 따옴표에 도달하기 전에 '와를 모두 해석합니다 . 필자는 일반적으로 불필요하더라도 반박 할 인용 부호를 큰 따옴표로 묶습니다. 예를 들면 다음과 같습니다."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}' `    '\'

또한 큰 따옴표를 사용할 수 있지만 $셸 을 이스케이프 처리 하여 쉘이 변수로 해석하지 못하도록하고 백틱을 지정하면 셸에서 명령 대체를 즉시 실행하지 않습니다.

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

7

Michael Mrozek의 답변 이 이것을 잘 다루기 때문에 귀하의 시도가 왜 그렇게 행동하는지에 대해서는 자세히 설명하지 않겠습니다 . 간단히 말해서, 작은 따옴표 사이의 모든 ( '…') 문자 (첫 번째, 특히 해석 '마크 리터럴 문자열의 끝) 반면, `와 $사이에 자신의 특별한 의미를 유지 "…".

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

echo 'foo'\''bar'

이 인쇄는 foo'bar인수가 있기 때문에, echo단일 인용 세 문자열 구성되어 foo단일 문자와 연결, '(문자를 보호하여 얻은 '이전을 통해 특별한 의미에서 \단일 인용 세 문자열와 연결) bar. 따라서이면에서 일어나는 일은 아니지만 '\'', 작은 따옴표로 묶은 문자열 안에 작은 따옴표를 포함시키는 방법으로 생각할 수 있습니다 .

복잡한 여러 줄 문자열을 인쇄하려면 here document 가 더 좋습니다 . here 문서는 두 문자로 구성됩니다<< 와 <<EOF, 다음 과 같은 마커 , 텍스트 라인, 끝 마커만으로 구성됩니다. 마커가 어떤 식 으로든 ( 'EOF'또는 "EOF"또는 \EOF'E ""OF'또는 ...) 따옴표로 묶인 경우 텍스트는 문자 그대로 해석됩니다 ( '일반 문자를 제외하고 작은 따옴표 내부와 같이 ). 마커가 전혀 인용되지 않은 경우 텍스트는 큰 따옴표로 표시된 것처럼 $\`특수 상태 를 유지하면서 "해석됩니다 (그러나 개행은 문자 그대로 해석 됨).

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

1

좋아, 이것은 작동합니다 :-

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}' ` 

0

here 문서 사용에 대한 Gilles의 제안 은 정말 좋으며 Perl과 같은 스크립팅 언어에서도 작동합니다. OP 문제에 대한 그의 답변을 바탕으로 한 구체적인 예로서,

use strict;
my $cmd = q#cat <<'EOF' # . "\n" .
          q#echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `# . "\n" .
          q#EOF# ;
open (my $OUTPUT, "$cmd |");
print $_ while <$OUTPUT>;
close $OUTPUT;

물론,이 예제는 약간 고안되었지만 SQL 문을 psql대신 보내는 데 유용한 기술이라는 것을 알았습니다.cat .

(알파벳이 아닌 비 공백 문자는 위의 #일반 인용 구문 에서 대신 사용될 수 있지만 해시는이 예제에서 잘 드러난 것처럼 보이며 주석으로 처리 되지 않습니다 .)


-1

당신의 명령을 보자

$ 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 PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print } `    ”

이 단계별 지침으로 관찰 된 동작이 더 명확 해지기를 바랍니다. 이 문제를 피하려면 다음과 같이 작은 따옴표를 이스케이프하십시오.

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

작은 따옴표로 묶인 문자열을 종료 한 다음 단어에 (이스케이프 된) 작은 따옴표를 추가 한 다음 단어를 구분하지 않고 새로운 작은 따옴표로 묶인 문자열을 시작합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.