다른 스크립트의 내용으로 사용할 변수를 이스케이프 처리


20

이 질문은 올바르게 이스케이프 된 문자열 리터럴을 작성하는 방법에 관한 것이 아닙니다 . 스크립트 또는 다른 프로그램에서 직접 소비하기 위해 변수를 이스케이프 처리하는 방법에 관한 관련 질문을 찾을 수 없습니다.

내 목표는 스크립트가 다른 스크립트를 생성 할 수있게하는 것입니다. 생성 된 스크립트의 작업은 다른 컴퓨터 에서 0에서 n 번 까지 실행 되며 생성 된 데이터는 실행되기 전에 변경 될 수 있으므로 네트워크를 통해 직접 작업을 수행하기 때문입니다. 작동하지.

같은 작은 따옴표와 같은 특수 문자를 포함 할 수 있습니다 알려진 변수를 감안할 때, 나는 예를 들어 변수 완전히 탈출 문자열 리터럴로 그를 쓸 필요가 foo포함 bar'baz생성 된 스크립트로 표시되어야합니다 :

qux='bar'\''baz'

"qux=$foo_esc"스크립트의 다른 줄 에 추가 하여 작성합니다 . 나는 Perl을 다음과 같이 사용했다.

foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"

그러나 이것은 과도한 것으로 보입니다.

나는 bash만으로는 성공하지 못했습니다. 나는 이것들의 많은 변형을 시도했다.

foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"

그러나 추가 슬래시가 출력에 나타나거나 (내가 할 때 echo "$foo") 구문 오류가 발생합니다 (쉘에서 수행하면 추가 입력이 예상 됨).


alias및 / 또는 set상당히 보편적으로
mikeserv

@mikeserv 죄송합니다, 무슨 뜻인지 모르겠습니다.
Walf

alias "varname=$varname" varname또는var=value set
mikeserv

2
@ mikeserv 그것은 당신의 제안이 무엇을 해야하는지, 그것을 변수를 탈출하는 일반적인 방법으로 사용하는 방법을 이해하기에 충분하지 않습니다. 해결 된 문제 야, 친구
Walf

답변:


27

Bash에는 정확히이 경우에 대한 매개 변수 확장 옵션이 있습니다 .

${parameter@Q}확장은 입력으로 재사용 할 수있는 형식으로 인용 된 매개 변수 의 값인 문자열입니다 .

따라서이 경우 :

foo_esc="${foo@Q}"

이것은 Bash 4.4 이상에서 지원됩니다. 다른 형식의 확장 및 전체 지정 문 ( @A) 을 구체적으로 생성하기위한 여러 옵션이 있습니다 .


7
단정하지만 4.2 만 제공합니다 bad substitution.
Walf

3
Z 쉘에 해당하는 값은 "${foo:q}"입니다.
JdeBP

정말 내 생명을 구해! "${foo@Q}"공장!
hao

Z 쉘과 동등한 기능이 작동하지 않는 @JdeBP. zsh에 대한 다른 아이디어가 있습니까?
Steven Shaw

1
답을 찾았습니다 : "$ {(@ qq) foo}"
Steven Shaw

11

Bash는 printf내장 된 %q형식 지정자를 제공 합니다.이 지정자는 구형 (<4.0) 버전의 Bash에서도 쉘 이스케이프를 수행합니다.

printf '[%q]\n' "Ne'er do well"
# Prints [Ne\'er\ do\ well]

printf '[%q]\n' 'Sneaky injection $( whoami ) `ls /root`'
# Prints [Sneaky\ injection\ \$\(\ whoami\ \)\ \`ls\ /root\`]

이 트릭은 함수에서 데이터 배열을 반환하는 데 사용될 수도 있습니다.

function getData()
{
  printf '%q ' "He'll say hi" 'or `whoami`' 'and then $( byebye )'
}

declare -a DATA="( $( getData ) )"
printf 'DATA: [%q]\n' "${DATA[@]}"
# Prints:
# DATA: [He\'ll\ say\ hi]
# DATA: [or\ \`whoami\`]
# DATA: [and\ then\ \$\(\ byebye\ \)]

Bash printf내장 기능은 printf대부분의 Unix 계열 운영 체제와 함께 제공되는 유틸리티와 다릅니다 . 어떤 이유로 printf명령이 내장 대신 유틸리티를 호출하는 경우 항상 builtin printf대신 실행할 수 있습니다 .


출력 해야 할 'Ne'\''er do well'따옴표 등 이 인쇄에 필요한지 어떻게 도움이되는지 잘 모르겠습니다 .
Walf

1
@Walf 두 형식이 동일하며 두 형식이 서로 완벽하게 안전하다는 것을 이해하지 못한다고 생각합니다. 예는 [[ 'Ne'\''er do well' == Ne\'er\ do\ well ]] && echo 'equivalent!'메아리equivalent!
Dejay 클레이튼에게

나는 그것을 그리워했다.
Walf

@ Walf 그것은 당신의 접근 방식이 꽤 위험한 것처럼 보입니다. 예를 들어 Perl 'hello'에서 잘못된 value 와 같은 값을 전달 ''\''hello''하면 불필요한 선행 빈 문자열 (처음 두 작은 따옴표)과 부적절한 작은 따옴표가 있습니다.
Dejay Clayton

1
설명을 위해 @Walf 는 Bash $'escape-these-chars'ANSI-C 인용 기능으로 지정된 문자열 내의 모든 문자를 이스케이프합니다. 따라서 파일 이름 내에 개행 문자를 포함하는 문자열 리터럴을 쉽게 만들려면 (예 : 이 구문 내 $'first-line\nsecond-line')에서 사용)\n
Dejay Clayton

8

RTFM이 아닌 것 같습니다. 그렇게 할 수 있습니다 :

q_mid=\'\\\'\'
foo_esc="'${foo//\'/$q_mid}'"

그런 다음 echo "$foo_esc"예상'bar'\''baz'


실제로 그것을 사용하는 방법은 함수입니다.

function esc_var {
    local mid_q=\'\\\'\'
    printf '%s' "'${1//\'/$mid_q}'"
}

...

foo_esc="`esc_var "$foo"`"

printfDejay 솔루션 의 내장 기능 을 사용하도록 수정 :

function esc_vars {
    printf '%q' "$@"
}

3
내 버전에서 지원하는 경우 @ michael-homer의 솔루션을 사용합니다.
Walf

4

var 값을 인용하는 몇 가지 솔루션이 있습니다.

  1. alias
    대부분의 쉘에서 (alias가 사용 가능한 경우) (csh, tcsh 및 아마도 다른 csh는 제외) :

    $ alias qux=bar\'baz
    $ alias qux
    qux='bar'\''baz'

    예, 이것은 sh대시 또는 애쉬와 같은 많은 쉘 에서 작동합니다 .


  2. 또한 대부분의 쉘에서 (csh가 아닌) 다시 설정 하십시오.

    $ qux=bar\'baz
    $ set | grep '^qux='
    qux='bar'\''baz'

  3. 일부 셸에서 조판 (ksh, bash 및 zsh 이상) :

    $ qux=bar\'baz
    $ typeset -p qux
    typeset qux='bar'\''baz'             # this is zsh, quoting style may
                                         # be different for other shells.
  4. 수출
    먼저해야 할 일 :

    export qux=bar\'baz

    그런 다음 사용하십시오 :
    export -p | grep 'qux=' export -p | grep 'qux='
    export -p qux

  5. 인용
    echo "${qux@Q}"
    echo "${(qq)qux}" 하나에서 4 Q 년대에 #을 사용할 수있다.


별칭 접근 방식은 영리하며 POSIX에서 지정한 것처럼 보입니다. 최고의 휴대 성을 위해 이것이 최선의 방법이라고 생각합니다. 포함 된 줄 바꿈이 포함 된 변수 grep와 관련된 export또는 제안 set이 깨질 수 있다고 생각합니다 .
jw013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.