명령 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}'\'' ` '
그러면 작은따옴표 문자열이 끝나고 단어에 (이스케이프 처리된) 작은따옴표가 추가된 다음 단어를 분할하지 않고 새 작은따옴표 문자열이 시작됩니다.