programing

따옴표로 묶인 단일 문자열 내에서 단일 따옴표를 이스케이프하는 방법

nicescript 2023. 4. 22. 22:55
반응형

따옴표로 묶인 단일 문자열 내에서 단일 따옴표를 이스케이프하는 방법

를 들어,이 Bash를 있다고 가정해봅시다.alias들면 다음과 같습니다.

alias rxvt='urxvt'

잘 작동하죠.

단,

alias rxvt='urxvt -fg '#111111' -bg '#111111''

동작하지 않습니다.또한 동작하지 않습니다.

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

그러면 이스케이프된 따옴표를 사용하여 문자열 내에서 여는 따옴표와 닫는 따옴표를 일치시키는 방법은 무엇일까요?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

이렇게 연결하면 같은 문자열을 나타낼 수 있지만 보기 흉하게 느껴집니다.

맨 바깥쪽 레이어에서 단일 따옴표를 사용하려면 두 종류의 따옴표를 모두 붙일 수 있습니다.예:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

'"'"'라고 되고 있다로 ':

  1. '작은 따옴표를 사용하는 첫 번째 따옴표를 끝냅니다.
  2. "큰따옴표를 사용하여 두 번째 따옴표를 시작합니다.
  3. '따옴표로 묶은 문자
  4. "큰따옴표를 사용하여 두 번째 따옴표를 끝냅니다.
  5. '작은 따옴표를 사용하여 세 번째 따옴표를 시작합니다.

(1)과 (2) 사이 또는 (4)와 (5) 사이에 공백 공간을 두지 않으면 셸은 해당 문자열을 하나의 긴 단어로 해석합니다.

한 줄한 줄 한 줄 한 ''따옴표'로 바꾸면 요.'\''는 따옴표를 을 다시 (따옴표, backslash quote) 。


Perl 스크립트에서 이 작업을 수행하기 위해 "quotify" 함수를 자주 실행합니다.순서는 다음과 같습니다.

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

이것으로 모든 사건을 처리할 수 있습니다.

소개하면 이 더 .eval네 껍데기 안에 넣어.기본적으로 모든 견적을 다시 작성해야 합니다!

예를 들어 위의 문장을 포함하는 quotify라는 이름의 Perl 스크립트를 만듭니다.

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

그런 다음 올바른 문자열 생성에 사용합니다.

$ quotify
urxvt -fg '#111111' -bg '#111111'

결과:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

그런 다음 alias 명령에 복사/붙일 수 있습니다.

alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

(명령어를 평가에 삽입해야 할 경우 견적서를 다시 실행합니다.

 $ quotify
 alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

결과:

'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

평가판에 복사/붙일 수 있습니다.

eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

Bash 2.04 구문 이후$'string'는 탈출 제한 세트를 허용합니다.

4.4 , Bash 4.4 」$'string'또, C스타일의 완전한 이스케이프 세트를 사용할 수 있기 때문에, 동작은 약간 다릅니다.$'string'$('string')형식을 사용할 수 있습니다.)

Bash 2.04 이후의 간단한 예:

  $> echo $'aa\'bb'
  aa'bb

  $> alias myvar=$'aa\'bb'
  $> alias myvar
  alias myvar='aa'\''bb'

고객님의 경우:

$> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
$> alias rxvt
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

일반적인 이스케이프 시퀀스는 예상대로 작동합니다.

\'     single quote
\"     double quote
\\     backslash
\n     new line
\t     horizontal tab
\r     carriage return

입니다.man bash.4 (버전 4.4):

$'string' 형식의 단어는 특별 취급됩니다.ANSI C 표준에서 지정한 대로 백슬래시 이스케이프 문자를 사용하여 단어가 문자열로 확장됩니다.백슬래시 이스케이프 시퀀스(존재하는 경우)는 다음과 같이 디코딩됩니다.

    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \?     question mark
    \nnn   the eight-bit character whose value is the octal 
           value nnn (one to three digits)
    \xHH   the eight-bit character whose value is the hexadecimal
           value HH (one or two hex digits)
    \uHHHH the Unicode (ISO/IEC 10646) character whose value is 
           the hexadecimal value HHHH (one to four hex digits)
    \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
               is the hexadecimal value HHHHHHHH (one to eight 
               hex digits)
    \cx    a control-x character

확장된 결과는 달러 기호가 없었던 것처럼 단일 따옴표로 묶습니다.


자세한 내용은 bash-hackers.org Wiki의 따옴표와 이스케이프: ANSI C like 문자열을 참조하십시오., 「Bash Changes」파일(여기서 개요)에서는, 다음과 같은 변경이나 버그 수정에 대해 많은 것을 언급하고 있습니다.$'string'견적 메커니즘

unix.stackexchange.com에 따르면 특수 문자를 일반 문자로 사용하는 방법은?bash, zsh, mksh, ksh93 및 FreeBSD 및 busybox sh에서 (일부 변형으로) 동작합니다.

그의 블로그(link pls?)에는 엔트리가 표시되지 않지만 gnu 레퍼런스 매뉴얼에 따르면:

작은 따옴표("")로 문자를 묶으면 따옴표 안에 있는 각 문자의 리터럴 값이 유지됩니다.백슬래시가 선행되는 경우에도 단일 따옴표는 단일 따옴표 사이에 발생할 수 없습니다.

bash가 이해하지 못하게:

alias x='y \'z '

단, 큰따옴표로 둘러싸면 이 작업을 수행할 수 있습니다.

alias x="echo \'y "
> x
> 'y

하다, 라고 하면 알 수 .'\''단일 따옴표로 묶인 문자열 내의 단일 따옴표는 Bash에서 작동하며, 스레드의 앞부분의 "gling" 인수와 같은 방법으로 설명할 수 있습니다.가 붙은 문자열이 해 보겠습니다.'A '\''B'\'' C'(여기에서는 모든 따옴표는 작은 따옴표입니다).됩니다.A 'B' C. . 。'\'' 번째 는 현재 문자열을 은 단일 문자 문자열입니다.행방불안내리다\'(따옴표).\'따옴표로 묶인 문자열을 시작하지 않고 단일 따옴표를 지정하는 방법)으로, 마지막 따옴표로 다른 단일 따옴표가 열립니다.

두 버전 모두 이스케이프된 작은따옴표 문자(\')를 사용하여 연결하거나 큰따옴표("") 안에 작은따옴표 문자를 넣어 연결하거나 둘 중 하나입니다.

질문 작성자는 마지막 탈출 시도 끝에 다음과 같은 작은 따옴표(')가 추가된 것을 알아차리지 못했습니다.

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
           │         │┊┊|       │┊┊│     │┊┊│       │┊┊│
           └─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      └┴─────────┴┴───┰───┴┴─────────┴┘│
                          All escaped single quotes    │
                                                       │
                                                       ?

ASCII/Unicode art의 이전 부분과 같이 마지막 이스케이프된 단일 따옴표(\') 뒤에 불필요한 단일 따옴표(')가 붙습니다.Notepad++에 있는 구문 강조 표시를 사용하면 매우 유용합니다.

다음 예와 같은 다른 예에서도 마찬가지입니다.

alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'

이 두 가지 아름다운 에일리어스 인스턴스는 파일을 어떻게 정렬할 수 있는지 매우 복잡하고 난독화된 방식으로 보여줍니다.즉, 행이 많은 파일에서는, 앞의 행의 내용 사이에 쉼표와 공백이 있는 행이 1 행 밖에 없습니다.앞의 코멘트를 이해하기 위해서, 예를 다음에 나타냅니다.

$ cat Little_Commas.TXT
201737194
201802699
201835214

$ rc Little_Commas.TXT
201737194, 201802699, 201835214

셸에서 따옴표를 이스케이프하는 간단한 예:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

것을.'1(「스이이 escaped ), ), 。\'FONT CHANGE:>( ).'이 명령어에 됩니다.) 이 구문은 모든 명령어에 적용됩니다.첫 번째 답과 매우 비슷한 접근법입니다.

때로는 다른 방법을 고려하는 것이 합리적이기 때문에 견적 문제를 구체적으로 언급하는 것은 아닙니다.

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

그 후, 다음과 같이 호출할 수 있습니다.

rxvt 123456 654321

따옴표를 신경 쓰지 않고 이 에일리어스를 붙일 수 있게 되었습니다.

alias rxvt='rxvt 123456 654321'

「 」를 경우는,#어떤 이유로든 모든 콜에 응답합니다.

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

그 후, 다음과 같이 호출할 수 있습니다.

rxvt '#123456' '#654321'

물론 에일리어스는 다음과 같습니다.

alias rxvt="rxvt '#123456' '#654321'"

(예상치 않습니다만, 제가 견적을 냈던 것 같습니다.)

대부분의 경우 마커를 사용한 주요 답변이 최선의 답변입니다.하지만 그렇지 않은 경우에는 다음과 같이 대답합니다.

( 「」 「」 「」 「」 「」'와 큰따옴표( )"16진수 및 8진수 문자 포함)

를 들어서 '하다'라고 하면echo나는 매우 복잡하고, 매우 이상하고, 피하기 어려운(생각: 매우 중첩된) 케이스가 있어, 내가 일할 수 있는 유일한 방법은 8진수 코드나 16진수 코드를 사용하는 것이었다.

다음은 작동 방식을 설명하기 위한 몇 가지 기본적인 예입니다. '아예'를해 주세요.-e " " " option to " " option to " )echo하다

예 1.따옴표로 묶은 예'16진법으로 이스케이프되다 \x27또는 8진수 \047(해당 ASCII 코드):

  1. 인치 16 인치\x27

    echo -e "Let\x27s get coding!"
    # OR
    echo -e 'Let\x27s get coding!'
    

    결과:

    Let's get coding!
    
  2. \047

    echo -e "Let\047s get coding!"
    # OR
    echo -e 'Let\047s get coding!'
    

    결과:

    Let's get coding!
    

예. 츠요시"16진법으로 이스케이프되다 \x22또는 8진수 \042(대응하는 ASCII 코드).

★★★★★★bash미쳤어!경우에 따라서는 char조차 특별한 의미를 가지기 때문에 큰따옴표 안에서 삭제한 후 이스케이프해야 합니다."like this"\!에 다 수도 요.'like this!'(이것들)

# 1. hex; also escape `!` by removing it from within the double quotes 
# and escaping it with `\!`
$ echo -e "She said, \x22Let\x27s get coding"\!"\x22"
She said, "Let's get coding!"

# OR put it all within single quotes:
$ echo -e 'She said, \x22Let\x27s get coding!\x22'
She said, "Let's get coding!"


# 2. octal; also escape `!` by removing it from within the double quotes 
$ echo -e "She said, \042Let\047s get coding"\!"\042"
She said, "Let's get coding!"

# OR put it all within single quotes:
$ echo -e 'She said, \042Let\047s get coding!\042'
She said, "Let's get coding!"


# 3. mixed hex and octal, just for fun
# also escape `!` by removing it from within the double quotes when it is followed by
# another escape sequence
$ echo -e "She said, \x22Let\047s get coding! It\x27s waaay past time to begin"\!"\042"
She said, "Let's get coding! It's waaay past time to begin!"

# OR put it all within single quotes:
$ echo -e 'She said, \x22Let\047s get coding! It\x27s waaay past time to begin!\042'
She said, "Let's get coding! It's waaay past time to begin!"

위에서 설명한 바와 같이 필요에 따라 적절히 이스케이프를 하지 않으면 다음과 같은 이상한 오류가 발생합니다.

$ echo -e "She said, \x22Let\047s get coding! It\x27s waaay past time to begin!\042"
bash: !\042: event not found

또는:

$ echo -e "She said, \x22Let\x27s get coding!\x22"
bash: !\x22: event not found

다른 방법으로는 동일한 bash 문자열 내에서 확장과 비확장이 모두 혼재됩니다.

여기 또 다른 이스케이프 기술의 데모가 있습니다.

먼저 @liori의 주요 답변을 읽고 아래 두 번째 폼이 어떻게 작동하는지 확인하십시오.이제 이 두 가지 대체 문자 탈출 방법을 읽어 보십시오.다음 두 예시는 모두 동일한 출력입니다.

CMD="gs_set_title"

# 1. 1st technique: escape the $ symbol with a backslash (\) so it doesn't 
# run and expand the command following it
echo "$CMD '\$(basename \"\$(pwd)\")'"

# 2. 2nd technique (does the same thing in a different way): escape the 
# $ symbol using single quotes around it, and the single quote (') symbol
# using double quotes around it
echo "$CMD ""'"'$(basename "$(pwd)")'"'"

샘플 출력:

gs_set_title '$(basename "$(pwd)")'
gs_set_title '$(basename "$(pwd)")'

제 의 my의 : 제gs_set_titlebash 함수는 이 근처에 있는 파일에 있습니다.여기서 다른 답을 보세요.

참고 자료:

  1. https://en.wikipedia.org/wiki/ASCII#Printable_characters
  2. https://serverfault.com/questions/208265/what-is-bash-event-not-found/208266#208266
  3. 다른 답변도 참조하십시오.비 ASC 쓰기 방법echo를 사용하는 II 문자?

들면 「」와 같이 됩니다\x27 ★★★★★★★★★★★★★★★★★」\\x22★★★★★★★★★★★★★★★★★★★★★★★★★★★

따옴표로 묶은 단일 문자열 안에 단일 따옴표를 넣을 수 없기 때문에 가장 간단하고 읽기 쉬운 옵션은 GREEDOC 문자열을 사용하는 것입니다.

command=$(cat <<'COMMAND'
urxvt -fg '#111111' -bg '#111111'
COMMAND
)

alias rxvt=$command

가 의의 greed 、 TREADOC 、 음음음음 the the the the the the the the the the the the the로 전송됩니다.cat 및 그 표기법 「」을 됩니다.$(..)

는 TREADOC 내에 붙여야 .$()

나는 웅변하는 사람들을 훑어봐야 했기 때문에 사람들이 많은 시간을 보내지 않고 지낼 수 있도록 최소한의 답변이 필요하다.

작은 따옴표나 작은 따옴표 안에 있는 다른 어떤 것도 피할 수 없습니다.

다음은 의외로 완전한 명령어입니다.

$ echo '\'

출력은 다음과 같습니다.

\

백슬래시는 놀랍게도 bash의 오랜 사용자도 작은 따옴표 안에 의미가 없습니다.다른 것도 마찬가지야.

IMHO의 진짜 답은 단일 따옴표로 묶인 문자열 내에서 단일 따옴표를 피할 수 없다는 것입니다.

그건 불가능해.

우리가 bash를 사용하고 있다고 가정하면.

bash 매뉴얼에서...

Enclosing characters in single quotes preserves the literal value of each
character within the quotes.  A single quote may not occur
between single quotes, even when preceded by a backslash.

다른 문자열 이스케이프 메커니즘 " 또는 \ 중 하나를 사용해야 합니다.

에 about there there there there 。alias작은 따옴표를 사용해야 합니다.

다음 두 가지 모두 bash에서 작동합니다.

alias rxvt="urxvt -fg '#111111' -bg '#111111'"
alias rxvt=urxvt\ -fg\ \'#111111\'\ -bg\ \'#111111\'

후자는 \를 사용하여 공백 문자를 이스케이프합니다.

#1111에도 작은 따옴표가 필요한 마법은 없습니다.

다음 옵션은 rxvt 에일리어스가 예상대로 동작한다는 점에서 다른 두 가지 옵션과 동일한 결과를 얻을 수 있습니다.

alias rxvt='urxvt -fg "#111111" -bg "#111111"'
alias rxvt="urxvt -fg \"#111111\" -bg \"#111111\""

번거로운 #에서 직접 벗어날 수도 있습니다.

alias rxvt="urxvt -fg \#111111 -bg \#111111"

이 답변의 대부분은 당신이 묻고 있는 특정 사례에 부합합니다.ssh를 여러 의 셸를 들어 ssh를 통해 bash 명령어를 인용할 수 있습니다.su -c,bash -c bash에는 '원어민 bash입니다."Bash" :

quote_args() {
    local sq="'"
    local dq='"'
    local space=""
    local arg
    for arg; do
        echo -n "$space'${arg//$sq/$sq$dq$sq$dq$sq}'"
        space=" "
    done
}

이것은 정확히 다음과 같이 동작합니다.각 인수는 (물론 bash 확장 후) 셸 따옴표로 묶습니다.

$ quote_args foo bar
'foo' 'bar'
$ quote_args arg1 'arg2 arg2a' arg3
'arg1' 'arg2 arg2a' 'arg3'
$ quote_args dq'"'
'dq"'
$ quote_args dq'"' sq"'"
'dq"' 'sq'"'"''
$ quote_args "*"
'*'
$ quote_args /b*
'/bin' '/boot'

확장 레이어 1개에 대해서, 다음과 같은 작업을 실시합니다.

$ bash -c "$(quote_args echo a'"'b"'"c arg2)"
a"b'c arg2

(큰따옴표는,$(quote_args ...)합니다.bash -c 적절한 견적을 위해 할 수 또한 보다 일반적으로 여러 층의 확장을 통해 적절한 견적을 낼 수 있습니다.

$ bash -c "$(quote_args bash -c "$(quote_args echo a'"'b"'"c arg2)")"
a"b'c arg2

위의 예는 다음과 같습니다.

  1. .quote_args를 개별적으로 조합한 후 결과 출력을 안쪽 큰따옴표로 묶은 단일 인수에 결합합니다.
  2. 에 의한bash,-c스텝 1에서 이미1번 검색된 결과를 바깥쪽 큰따옴표로 둘러싸인 단일 인수로 결합합니다.
  3. mass를 로 한다.bash -c.

그게 요점이야.이것으로는 꽤 복잡한 작업을 할 수 있지만, 평가 순서와 인용되는 서브스트링에 대해 주의해야 합니다.예를 들어, 다음과 같은 경우('잘못'의 정의에 따라) 잘못된 작업을 수행합니다.

$ (cd /tmp; bash -c "$(quote_args cd /; pwd 1>&2)")
/tmp
$ (cd /tmp; bash -c "$(quote_args cd /; [ -e *sbin ] && echo success 1>&2 || echo failure 1>&2)")
failure

번째 예에서는 "bash"를 확장합니다.quote_args cd /; pwd 1>&2 명령어 「」로 합니다.quote_args cd / ★★★★★★★★★★★★★★★★★」pwd 1>&2 CWD는 'CWD'입니다/tmppwd명령어가 실행됩니다.두 번째 예는 지구본의 경우와 같은 문제를 나타내고 있습니다.실제로 모든 bash 확장에서 동일한 기본 문제가 발생합니다.여기서의 문제는 명령어 대체가 함수 호출이 아니라는 것입니다.이것은 문자 그대로 하나의 bash 스크립트를 평가하고 그 출력을 다른 bash 스크립트의 일부로 사용하는 것입니다.

셸 연산자를 이 에 되었기 때문에 bash -c연산자로 않는 bash에 알 수 있습니다.이러한 문자열은 bash에 전달된 문자열을 에코하면 쉽게 알 수 있습니다.

$ (cd /tmp; echo "$(quote_args cd /\; pwd 1\>\&2)")
'cd' '/;' 'pwd' '1>&2'
$ (cd /tmp; echo "$(quote_args cd /\; \[ -e \*sbin \] \&\& echo success 1\>\&2 \|\| echo failure 1\>\&2)")
'cd' '/;' '[' '-e' '*sbin' ']' '&&' 'echo' 'success' '1>&2' '||' 'echo' 'failure' '1>&2'

여기서의 문제는 당신이 너무 많은 견적을 낸다는 것입니다.은, 되어 있는 「」의 입니다.bash -c 말은 즉, '', '외부', '외부', '', '$(quote_args ...)명령어 대체

따라서 가장 일반적인 의미에서 필요한 것은 명령어 치환 시 개별적으로 확장되지 않는 명령어의 각 단어를 셸 따옴표로 묶는 것입니다.또한 셸 연산자에 추가 따옴표를 적용하지 마십시오.

$ (cd /tmp; echo "$(quote_args cd /); $(quote_args pwd) 1>&2")
'cd' '/'; 'pwd' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")
/
$ (cd /tmp; echo "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
'cd' '/'; [ -e *'sbin' ] && 'echo' 'success' 1>&2 || 'echo' 'failure' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
success

이 작업을 완료하면 전체 문자열이 임의의 평가 수준으로 추가 인용하기에 적합합니다.

$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")"
/
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")"
/
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")")"
/
$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")"
success
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *sbin ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")"
success
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")")"
success

기타.

은 '아주 좋다'와 같은 된 것처럼 수 있습니다.success,sbin , , , , 입니다.pwdshell-displayed일 필요는 없지만, 임의의 입력을 받아 스크립트를 작성할 때 기억해야 할 중요한 점은 인용할 필요가 없는 은 모두 인용하는 것입니다.왜냐하면, 유저가 언제 이 스크립트를 입력할지는 모르기 때문입니다.Robert'; rm -rf /.

커버 아래에서 무슨 일이 일어나고 있는지 더 잘 이해하기 위해 다음 두 가지 작은 도우미 기능을 사용할 수 있습니다.

debug_args() {
    for (( I=1; $I <= $#; I++ )); do
        echo -n "$I:<${!I}> " 1>&2
    done
    echo 1>&2
}

debug_args_and_run() {
    debug_args "$@"
    "$@"
}

명령어를 실행하기 전에 명령어에 대한 각 인수를 열거합니다.

$ debug_args_and_run echo a'"'b"'"c arg2
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)"
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'bash'"'"' '"'"'-c'"'"' '"'"''"'"'"'"'"'"'"'"'debug_args_and_run'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'echo'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'a"b'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'c'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'arg2'"'"'"'"'"'"'"'"''"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

이 예에서는 외부 이스케이프 메커니즘으로 작은 따옴표가 아닌 큰 따옴표를 사용했습니다.

alias rxvt="urxvt -fg '#111111' -bg '#111111'"

이 은 명령어에로 둘러싸인 합니다. 셸이 이중 따옴표로 묶인 문자열을 어떻게 해석하는지 확인하기만 하면 됩니다.echo및 필요에 따라 백슬래시를 사용하여 이스케이프 문자를 지정합니다.

이 예에서는 큰따옴표로 문자열을 보호할 수 있습니다.

$ echo "urxvt -fg '#111111' -bg '#111111'"
urxvt -fg '#111111' -bg '#111111'

다음은 위에서 언급한 하나의 정답에 대한 자세한 내용입니다.

가끔 rsync over ssh를 사용하여 다운로드 할 때 TWICE! (OMG!)1번 bash용, 1번 ssh용 파일명을 이스케이프해야 합니다.따옴표 구분자를 번갈아 사용하는 것과 같은 원리가 여기에도 작용하고 있습니다.

예를 들면, 예를 들면, 「Louis Theroux's LA Stories...」라고 합시다.

  1. 먼저 루이 서룩을 bash의 작은 따옴표와 ssh의 큰 따옴표로 묶습니다: "Louis Theroux"
  2. 그런 다음 작은따옴표를 사용하여 큰따옴표 '를 이스케이프합니다.
  3. 는 큰따옴표를 사용하여 아포스트로피를 이스케이프합니다.
  4. 그런 다음 작은따옴표를 사용하여 큰따옴표 '를 이스케이프하여 #2를 반복합니다.
  5. 그런 다음 LA Stories를 bash에는 작은따옴표로 묶고 ssh에는 큰따옴표로 묶습니다. "LA Stories"

그리고 보세요!이렇게 끝납니다.

rsync -ave ssh '"Louis Theroux"''"'"'"'"''"s LA Stories"'

작은 일치고는 엄청난 일이지만, 여기 있습니다.

물론 큰따옴표로 둘러싸는 것이 더 쉬울 것입니다만, 이 점에서 문제가 되는 것은 무엇입니까?여기 작은 따옴표만 사용한 답이 있습니다.가 지금 변수를 alias '인쇄할 수 있다', '인쇄할 수 있다', '인쇄할 수 있다'를 사용하는 것과 .alias.

$ rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'
$ echo $rxvt
urxvt -fg '#111111' -bg '#111111'

설명.

중요한 점은 단일 인용문을 닫았다가 원하는 횟수만큼 다시 열 수 있다는 것입니다.를 들어, 「」입니다.foo='a''b' is is is is is와 foo='ab'를 수 따옴표를 닫고 문자 그대로 따옴표를 넣을 수 있습니다.\'이치하다

내역도

이 다이어그램은 괄호를 사용하여 단일 따옴표가 열리고 닫히는 위치를 보여줌으로써 명확합니다.을 사용하다또한 올바르게 적용된 색상 강조 표시에도 주의를 기울일 수 있습니다.로 묶인 이지만 maroon은 maroon입니다.\'은색입입니니다

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'    # original
[^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^    # show open/close quotes
 urxvt -fg   ' #111111  '  -bg   ' #111111  '    # literal characters remaining

(이것은 기본적으로 Adrian의 답변과 동일하지만, 이것이 더 잘 설명되는 것 같습니다.또한 그의 답변은 마지막에 불필요한 작은 인용문 2개가 있습니다.)

@Jason 이외에우프 완벽한 대답 내가 어떻게 문제를 해결했는지 보여주고 싶다.

를 홑따옴표로 합니다.'\'' 경우 등 것은 입니다.

#!/bin/bash

# no closing quote
string='alecxs\'solution'

# this works for string
string="alecxs'solution"
string=alecxs\'solution
string='alecxs'\''solution'

문자열이 파일 이름이고 따옴표로 둘러싸인 파일 이름을 목록에 저장해야 한다고 가정합니다(stat -c%N ./* > list 등).

echo "'$string'" > "$string"
cat "$string"

그러나 이 목록 처리는 실패합니다(전체 문자열에 포함된 따옴표 수에 따라 다름).

while read file
  do
    ls -l "$file"
    eval ls -l "$file"
done < "$string"

회피책: 문자열 조작에 의한 따옴표 부호화

string="${string//$'\047'/\'\$\'\\\\047\'\'}"

# result
echo "$string"

인용문은 항상 균형이 잡혀있기 때문에 효과가 있다.

echo "'$string'" > list
while read file
  do
    ls -l "$file"
    eval ls -l "$file"
done < list

이것이 유사한 문제에 직면했을 때 도움이 되기를 바랍니다.

중첩된 인용문의 레이어가 너무 많은 문제를 해결하는 또 다른 방법은 다음과 같습니다.

너무 좁은 공간에 너무 많은 것을 밀어 넣으려고 하므로 bash 기능을 사용하십시오.

문제는 너무 많은 수준의 네스팅을 시도하고 있으며 기본적인 에일리어스 테크놀로지가 대응할 만큼 강력하지 않다는 것입니다.다음과 같은 bash 함수를 사용하여 단일 따옴표, 이중 따옴표 백틱 및 전달된 파라미터가 모두 예상대로 정상적으로 처리되도록 합니다.

lets_do_some_stuff() {
    tmp=$1                       #keep a passed in parameter.
    run_your_program $@          #use all your passed parameters.
    echo -e '\n-------------'    #use your single quotes.
    echo `date`                  #use your back ticks.
    echo -e "\n-------------"    #use your double quotes.
}
alias foobarbaz=lets_do_some_stuff

그러면 $1 및 $2 변수와 단일 따옴표, 이중 따옴표 및 백틱을 사용하여 별칭 함수가 무결성을 손상시킬 염려 없이 사용할 수 있습니다.

이 프로그램은 다음과 같이 인쇄합니다.

el@defiant ~/code $ foobarbaz alien Dyson ring detected @grid 10385
alien Dyson ring detected @grid 10385
-------------
Mon Oct 26 20:30:14 EDT 2015
-------------
shell_escape () {
    printf '%s' "'${1//\'/\'\\\'\'}'"
}

구현 설명:

  • 로 묶어서 할 수 .${...} 변경

  • 및과 같습니다.bash 검 、 색 、 음 、 음음음음음음음 。${varname//search/replacement}

  • ''\''

  • '\'' '다음과 같이 합니다.

    1. '

    2. \'「」를 한다.'합니다.)

    3. ' 한 번 인용하다

    4. bash는 공백 없이 문자열을 자동으로 연결합니다.

  • 이 there there there 있다\ 앞에\ ★★★★★★★★★★★★★★★★★」'도망치는 규칙이기 ${...//.../...}.

string="That's "'#@$*&^`(@#'
echo "original: $string"
echo "encoded:  $(shell_escape "$string")"
echo "expanded: $(bash -c "echo $(shell_escape "$string")")"

추신. 따옴표로 묶은 문자열은 따옴표로 묶은 문자열보다 훨씬 단순하므로 항상 따옴표로 묶은 문자열로 인코딩하십시오.

내 . . 면약면면면면면면면면면면면면면면면sh- 만 - ★★★★★★★★★ - -bash효율적이지 ) -specific(은 매우 효율적이지 않습니다).sed

  • 을 넣다quote.sh 그냥)quote의 에 있습니다.PATH:
# 이것은 표준 입력으로 동작합니다(stdin).따옴표() {echo -n ";sed 's/\(['''][']*/''\1''/g';echo -n " "}
케이스 "1달러"-) 따옴표;;*) 에코 "cat: cat..."| quote - # Bourne 쉘의 단일 따옴표 입력" 2 > & 1 ;esac

예:

$ echo - n "안녕하세요, 친구!" | ./견적.sh -안녕, 친구!

그리고 물론, 이는 다음과 같이 변환됩니다.

G''day, 친구!안녕, 친구!

설명: 기본적으로 입력 내용을 따옴표로 묶어야 합니다.'도 이 '"'"'' , . -- , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,"'"으로 첫 발행합니다.': , , " " " " " " 입니다.' + "'" + ' == '"'"')

인 방법 중 는 ""를 사용하는 입니다.sed with음 、 with with 、 with with 、 with with:::::: 。

s/\(['][']*\)/'"\1"'/g 

하지만 한 가지 작은 문제는 쉘에 그것을 사용하기 위해서는 sed 표현 자체에 있는 모든 작은 따옴표 문자에서 벗어나야 한다는 것입니다.그것은 다음과 같은 결과를 초래합니다.

sed 's/\(['"'"']['"'"']*\)/'"'"'"\1"'"'"'/g' 

이 중 (원래 표현)을 입력하는 입니다.s/\(['][']*\)/'"\1"'/gReilly(라일리)

마지막으로, 입력이 다음에서 오기를 기대하는 것은 타당합니다.stdin를 통해 하면 이미 큰가 발생할 수 때문입니다.-- 맨 -- 、 -- -- -- 、 -- -- -- -- -- -- -- -- 。

./quote.sh --help」 、 는지 、 금) ) ) ) )

Python 2 또는 Python 3 내에서 셸 스트링을 생성하는 경우 인수를 인용하는 데 도움이 될 수 있습니다.

#!/usr/bin/env python

from __future__ import print_function

try:  # py3
    from shlex import quote as shlex_quote
except ImportError:  # py2
    from pipes import quote as shlex_quote

s = """foo ain't "bad" so there!"""

print(s)
print(" ".join([shlex_quote(t) for t in s.split()]))

다음과 같이 출력됩니다.

foo ain't "bad" so there!
foo 'ain'"'"'t' '"bad"' so 'there!'

GNU Parallel이 설치되어 있는 경우 내부 견적을 사용할 수 있습니다.

$ parallel --shellquote
L's 12" record
<Ctrl-D>
'L'"'"'s 12" record'
$ echo 'L'"'"'s 12" record'
L's 12" record

부터는 [20190222]도 합니다.--shellquote「 」:

$ parallel --shellquote --shellquote --shellquote
L's 12" record
<Ctrl-D>
'"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
$ eval eval echo '"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
L's 12" record

셸의 ).bash를 참조해 주세요.

이 기능은 다음과 같습니다.

quote () 
{ 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

할 수 있다'에 inside inside inside ' 합니다. 다음과 같이 합니다.

$ quote "urxvt -fg '#111111' -bg '#111111'"
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

작은 따옴표로 묶은 큰따옴표와 같이 인용할 행이 복잡해지면 변수 내에서 문자열을 인용하는 것이 매우 까다로워질 수 있습니다.이러한 케이스가 표시되는 경우는, 스크립트내에 인용할 필요가 있는 행을 정확하게 기입해 주세요(이와 같습니다).

#!/bin/bash

quote ()
{
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

while read line; do
    quote "$line"
done <<-\_lines_to_quote_
urxvt -fg '#111111' -bg '#111111'
Louis Theroux's LA Stories
'single quote phrase' "double quote phrase"
_lines_to_quote_

유언 출력:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
'Louis Theroux'\''s LA Stories'
''\''single quote phrase'\'' "double quote phrase"'

작은 따옴표 안에 있는 모든 문자열이 올바르게 따옴표로 묶입니다.

여기 또 다른 해결책이 있다.이 함수는 위의 투표된 답변에서 설명한 바와 같이 단일 인수를 사용하여 적절하게 따옴표를 사용합니다.

single_quote() {
  local quoted="'"
  local i=0
  while [ $i -lt ${#1} ]; do
    local ch="${1:i:1}"
    if [[ "$ch" != "'" ]]; then
      quoted="$quoted$ch"
    else
      local single_quotes="'"
      local j=1
      while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "'" ]]; do
        single_quotes="$single_quotes'"
        ((j++))
      done
      quoted="$quoted'\"$single_quotes\"'"
      ((i+=j-1))
    fi
    ((i++))
  done
  echo "$quoted'"
}

따라서 다음과 같이 사용할 수 있습니다.

single_quote "1 2 '3'"
'1 2 '"'"'3'"'"''

x="this text is quoted: 'hello'"
eval "echo $(single_quote "$x")"
this text is quoted: 'hello'

언급URL : https://stackoverflow.com/questions/1250079/how-to-escape-single-quotes-within-single-quoted-strings

반응형