이스케이프된 문자열을 에코하는 방법

이스케이프된 문자열을 에코하는 방법

Bourne Shell에서 $가 포함된 이스케이프 문자열을 에코하는 방법은 무엇입니까?

user@server:~$ cat test.sh 
#!/bin/sh
echo $1

user@server:~$ ./test.sh \$sad\$test
$sad$test

다음과 같이 이스케이프된 버전을 반환하고 싶습니다.

user@server:~$ ./test.sh \$sad\$test
\$sad\$test

나는 sed와 awk를 사용하여 몇 가지 트릭을 시도했지만 성공하지 못했습니다. 어떤 지침이라도 대단히 감사하겠습니다.

답변1

문자열이 "셸 인용"으로 표시되기를 원한다고 가정합니다.

이것인쇄 기능내장 명령은케시,세게 때리다, 그리고다루기 힘든모두 %q형식 지정자를 이해합니다. 실제 출력은 정규화되지 않으며 입력 문자열에 따라 달라질 수 있습니다(아래 참조). 출력 형식의 변경으로 인해 한 셸의 출력을 다른 셸에서 사용하지 못할 수도 있습니다(특히 대상 셸이 기능이 덜 풍부한 셸인 경우).금연 건강 증진 협회,스프린트, 등. ).

다루기 힘든매개변수 확장에서 직접 인용문을 생성하는 기능도 지원됩니다.

echo "${(q)1}"    # backslashes, with $'' for unprintable/invalid characters
echo "${(qq)1}"   # single quotes
echo "${(qqq)1}"  # double quotes
echo "${(qqqq)1}" # $'' quoting

"직접 수행"하고 싶다면 가장 쉽고 신뢰할 수 있는 방법은 자신만의 작은따옴표를 생성하는 것입니다. 간단한 알고리즘은 다음과 같습니다.

  1. 작은따옴표를 시퀀스로 변경합니다 '\''.
  2. 결과를 작은따옴표로 묶습니다.

작은 따옴표는 완전히 literal1 이기 때문에 Bourne과 같은 쉘에서 작동합니다 . 작은따옴표를 나타내려면 현재 작은따옴표 범위를 끝내고 백슬래시로 이스케이프된 작은따옴표를 제공하고 문자열의 나머지 부분에 작은따옴표를 다시 사용하세요. 위의 알고리즘은 연속된 작은따옴표와 문자열의 시작과 끝 부분에 있는 작은따옴표를 처리할 때 효율성이 떨어지지만 매우 안정적이고 구현이 매우 간단합니다.

1 다른 언어의 작은따옴표는 일반적으로 완전히 문자 그대로는 아닙니다(적어도 일반적으로 제한된 백슬래시 이스케이프를 허용합니다). 이것이 바로 생성할 인용 형식에 대한 모든 인용 규칙을 이해하는 것이 중요한 이유입니다(즉, 인용된 텍스트가 어떤 언어/문맥에서 사용될 것인지).


printf %q다음은 로컬에 설치된 셸의 몇 가지 예 입니다 .

for s in /bin/ksh {,/opt/local}/bin/bash {,/opt/local}/bin/zsh
do
  "$s" --version | head -1
  "$s" -c 'printf "%q\n" "$@"' - \$sad\$test \'mixed\ quotes\" back\`tick
  echo
done

산출:

  version         sh (AT&T Research) 1993-12-28 s+
'$sad$test'
$'\'mixed quotes"'
'back`tick'

GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

GNU bash, version 4.2.10(2)-release (i386-apple-darwin10.7.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

zsh 4.3.9 (i386-apple-darwin10.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

zsh 4.3.12 (i386-apple-darwin10.7.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

우리는 봤다케시작은 따옴표로 인용하는 것을 "선호"하는 것으로 보이며 $''어떤 경우에는 이 형식을 사용합니다. 다른 쉘은 주로 백슬래시 이스케이프를 사용하는 것 같습니다(비록 $''특정 문자가 있는 경우 이를 사용하지만).

답변2

작은따옴표로 묶습니다 \$sad\$test.

$ echo $SHELL
/bin/bash
$ ./test.sh '\$sad\$test'
\$sad\$test

답변3

test.sh \$sad\$test를 실행하면 test.sh스크립트가 $sad$test인수로 대신 수신됩니다 \$sad\$test. 그 이유는 쉘이 \$호출하기 전에 로 대체되기 때문입니다. 스크립트를 수신하려면 or를 수행해야 합니다.$test.sh\$sad\$testtest.sh '\$sad\$test'test.sh "\\\$sad\\\$test"

다음과 같이 자신을 설득해 보세요.

function cat1stpar() {
cat << EOF
$1
EOF
}
cat1stpar \$sad\$test
cat1stpar '\$sad\$test'
cat1stpar "\\\$sad\\\$test"

또한 일반적으로 echo $1사용하는 것은 위험합니다. 이렇게 하면:

./test.sh "aaa bbb"
./test.sh "aaa    bbb"

출력은 다음과 같습니다:

aaa bbb
aaa bbb

아니다:

aaa bbb
aaa    bbb

두 번째 출력을 원한다면 최소한 이 작업을 수행하여 echo "$1"인수 echo가 너무 많지 않고 하나의 인수를 받도록 해야 합니다.성격1. 전체 단어 토론을 보려면 Shell Man의 IFS 변수를 참조하세요.

어떤 사람들은 인쇄하기 전에 일부 문자를 변경하는 것보다 이것이 printf "%s\n" "$1"더 안전하다고 말하지만 아직 완전히 이해하지는 못합니다.echo "$1"echo

편집하다:

캐릭터 변경 에 관해서는 echo그냥 이해합니다. 노력하다:

echo "-n"
printf "%s\n" "-n"
./test.sh "-n"
cat1stpar "-n"

답변4

스크립트에서:

echo "${1//$/\\$}"

이는 쉘에 내장된 간단한 문자열 대체입니다. 이 구문은 ${[VARIABLE_NAME]//[PATTERN]/[REPLACEMENT]}전역 리터럴 문자열 대체에 사용됩니다.

왜 이 일을 하려는지 모르겠습니다. 스크립트는 실제로 사용자가 보낸 문자열을 보고합니다. \$sad\$test결과는 '$sad$test'작은따옴표를 사용하여 이스케이프된다는 점을 제외하면 정확히 동일한 문자열로 평가됩니다 $.

관련 정보