작은 따옴표로 묶인 문자열에서 작은 따옴표를 이스케이프하는 방법
다음 alias
과 같은 Bash가 있다고 가정 해 보겠습니다 .
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) 사이 또는 (4)와 (5) 사이에 공백을 두지 않으면 쉘은 해당 문자열을 하나의 긴 단어로 해석합니다.
나는 항상 각 삽입 된 작은 따옴표를 '\''
문자열을 닫고 이스케이프 된 작은 따옴표를 추가하고 문자열을 다시 여는 시퀀스 : (즉, 따옴표 백 슬래시 따옴표)로 바꿉니다.
필자는 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를 다시 실행하십시오.
$ quotify
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
결과:
'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
eval에 복사 / 붙여 넣기 할 수 있습니다.
eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
Bash 2.04 구문 $'string'
( 'string'
경고 : 혼동하지 마십시오 대신 $('string')
)은 ANSI C와 유사한 이스케이프 시퀀스 를 허용 하고 작은 따옴표 버전으로 확장 할 수있는 또 다른 인용 메커니즘입니다 .
간단한 예 :
$> 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) 에서 복사하여 붙여 넣은 관련 문서입니다 .
$ '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 위키에서 인용문 및 이스케이프 : ANSI C like strings 를 참조하십시오. 또한 "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에서 작동한다는 것을 확인할 수 있으며 스레드의 앞부분에서 "gluing"인수와 동일한 방식으로 설명 할 수 있습니다. 따옴표로 묶인 문자열이 있다고 가정 'A '\''B'\'' C'
합니다 (여기서 모든 따옴표는 작은 따옴표입니다). echo에 전달되면 다음을 인쇄합니다 A 'B' C
.. 각각 '\''
의 첫 번째 따옴표는 현재 작은 따옴표 문자열을 닫고, 다음 \'
은 작은 따옴표를 이전 문자열에 붙이고 ( \'
따옴표로 묶인 문자열을 시작하지 않고 작은 따옴표를 지정하는 방법), 마지막 따옴표는 다른 작은 따옴표 문자열을 엽니 다.
쉘에서 따옴표를 이스케이프하는 간단한 예 :
$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc
이미 열린 하나 ( '
)를 완료하고 이스케이프 된 하나 ( \'
)를 배치 한 다음 다른 하나 ( '
) 를 열면 완료 됩니다. 이 구문은 모든 명령에 적용됩니다. 첫 번째 답변과 매우 유사한 접근 방식입니다.
두 버전 모두 이스케이프 된 작은 따옴표 문자 (\ ')를 사용하여 연결하거나 작은 따옴표 문자를 큰 따옴표 ( "'")로 묶어 연결하는 방식으로 작동합니다.
질문의 작성자는 마지막 이스케이프 시도 끝에 추가 작은 따옴표 ( ')가 있다는 것을 알아 차리지 못했습니다.
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
│ │┊┊| │┊┊│ │┊┊│ │┊┊│
└─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
┊┊ ┊┊ ┊┊ ┊┊│
┊┊ ┊┊ ┊┊ ┊┊│
└┴─────────┴┴───┰───┴┴─────────┴┘│
All escaped single quotes │
│
?
이전의 멋진 ASCII / 유니 코드 아트에서 볼 수 있듯이 마지막 이스케이프 된 작은 따옴표 (\ ') 뒤에는 불필요한 작은 따옴표 (')가옵니다. Notepad ++에있는 것과 같은 구문 강조 표시기를 사용하면 매우 도움이 될 수 있습니다.
다음과 같은 다른 예에서도 마찬가지입니다.
alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'
이 두 가지 아름다운 별칭 인스턴스는 파일이 줄을 이을 수있는 방법을 매우 복잡하고 난독하게 보여줍니다. 즉, 행이 많은 파일에서 이전 행의 내용 사이에 쉼표와 공백이있는 한 행만 얻습니다. 이전 주석을 이해하기 위해 다음은 예입니다.
$ cat Little_Commas.TXT
201737194
201802699
201835214
$ rc Little_Commas.TXT
201737194, 201802699, 201835214
글쎄요, 때로는 대체 접근 방식을 고려하는 것이 합리적이기 때문에 인용 문제를 구체적으로 다루지 않습니다.
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'"
(죄송합니다, 나는 인용구를 다루었습니다.)
난 그냥 쉘 코드를 사용 .. 예를 들어, \x27
또는 \\x22
해당되는 경우. 정말 번거롭지 않습니다.
작은 따옴표로 묶인 문자열 안에 작은 따옴표를 넣을 수 없기 때문에 가장 간단하고 읽기 쉬운 옵션은 HEREDOC 문자열을 사용하는 것입니다.
command=$(cat <<'COMMAND'
urxvt -fg '#111111' -bg '#111111'
COMMAND
)
alias rxvt=$command
위의 코드에서 HEREDOC는 cat
명령으로 전송 되고 그 출력은 명령 대체 표기법을 통해 변수에 할당됩니다.$(..)
HEREDOC 주위에 작은 따옴표를 넣어야합니다. $()
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.
다른 문자열 이스케이프 메커니즘 "또는 \ 중 하나를 사용해야합니다.
alias
작은 따옴표를 사용하도록 요구하는 마술은 없습니다 .
다음 두 가지 모두 bash에서 작동합니다.
alias rxvt="urxvt -fg '#111111' -bg '#111111'"
alias rxvt=urxvt\ -fg\ \'#111111\'\ -bg\ \'#111111\'
후자는 \를 사용하여 공백 문자를 이스케이프합니다.
작은 따옴표가 필요한 # 111111에 대한 마법도 없습니다.
다음 옵션은 rxvt 별칭이 예상대로 작동한다는 점에서 다른 두 옵션과 동일한 결과를 얻습니다.
alias rxvt='urxvt -fg "#111111" -bg "#111111"'
alias rxvt="urxvt -fg \"#111111\" -bg \"#111111\""
번거로운 #에서 직접 벗어날 수도 있습니다.
alias rxvt="urxvt -fg \#111111 -bg \#111111"
이러한 답변의 대부분은 귀하가 요청하는 특정 사례에 해당합니다. 이 친구가 일반적인 접근 방식은 내가 임의 필요한 경우 인용을 허용하는 개발에 인용 bash는 명령 ssh를 통해 쉘 확장, 예를 들어, 여러 계층을 통해, su -c
, bash -c
, 하나 개의 코어 원시 여기 필요가있다 등 기본 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'
하나의 확장 레이어에 대해 분명한 일을합니다.
$ 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
위의 예 :
- 각 인수를 내부에
quote_args
개별적으로 쉘 인용 한 다음 결과 출력을 내부 큰 따옴표가있는 단일 인수로 결합합니다. - shell-quotes
bash
,-c
및 1 단계에서 이미 한 번 인용 된 결과를 사용한 다음 결과를 외부 큰 따옴표가있는 단일 인수로 결합합니다. - 그 엉망을 외부 인수로 보냅니다
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
첫번째 예에서, 팽창 배시 즉시 quote_args cd /; pwd 1>&2
두 개의 명령어로, quote_args cd /
그리고 pwd 1>&2
CWD가 여전히 있으므로 /tmp
경우에 pwd
명령이 실행된다. 두 번째 예는 globbing에 대한 유사한 문제를 보여줍니다. 실제로 모든 bash 확장에서 동일한 기본 문제가 발생합니다. 여기서 문제는 명령 대체가 함수 호출이 아니라는 것입니다. 문자 그대로 하나의 bash 스크립트를 평가하고 그 출력을 다른 bash 스크립트의 일부로 사용하는 것입니다.
단순히 쉘 연산자를 이스케이프하려고하면 전달 된 결과 문자열이 bash -c
연산자로 해석되지 않고 개별적으로 인용 된 문자열의 시퀀스 이기 때문에 실패합니다. 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
그리고 pwd
쉘 인용 할 필요는 없지만, 임의의 입력을 복용하는 스크립트를 작성할 때 키 포인트는 기억하면 당신이 절대적으로 확실하지 않은 모든 인용 할 것입니다 '아무튼를 t는 사용자가 던질 때 당신이 알고하지 않기 때문에, 인용 필요 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'
위에서 언급 한 The One True Answer에 대한 자세한 설명은 다음과 같습니다.
때로는 ssh를 통해 rsync를 사용하여 다운로드하고 '가있는 파일 이름을 두 번 이스케이프해야합니다! (OMG!) bash에 한 번, ssh에 한 번. 따옴표 구분 기호를 번갈아 사용하는 동일한 원칙이 여기에서 작동합니다.
예를 들어, 우리가 원한다고 가정 해 봅시다 : Louis Theroux의 LA Stories ...
- 먼저 Louis Theroux를 bash의 경우 작은 따옴표로, ssh의 경우 큰 따옴표로 묶습니다. ' "Louis Theroux"'
- 그런 다음 작은 따옴표를 사용하여 큰 따옴표 ' "'를 이스케이프합니다.
- 큰 따옴표를 사용하여 아포스트로피 " '"를 이스케이프합니다.
- 그런 다음 작은 따옴표를 사용하여 큰 따옴표 ' "'를 이스케이프 처리하여 # 2를 반복합니다.
- 그런 다음 LA Stories를 bash의 경우 작은 따옴표로, ssh의 경우 큰 따옴표로 묶습니다. ' "LA Stories"'
그리고 보라! 다음과 같이 끝납니다.
rsync -ave ssh '"Louis Theroux"''"'"'"'"''"s LA Stories"'
한 번에 끔찍한 작업이긴하지만
중첩 된 인용문이 너무 많은 문제를 해결하는 또 다른 방법 :
너무 작은 공간에 너무 많이 넣으려고하므로 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}
우리는 교체하고
'
함께'\''
'\''
다음'
과 같이 단일 인코딩합니다 .'
작은 인용을 끝낸다\'
인코딩합니다'
(따옴표 안에 있지 않기 때문에 백 슬래시가 필요합니다)'
다시 작은 따옴표를 시작bash는 사이에 공백이없는 문자열을 자동으로 연결합니다.
거기의
\
모든 전에\
그리고'
그 때문에의 탈출 규칙입니다${...//.../...}
.
string="That's "'#@$*&^`(@#'
echo "original: $string"
echo "encoded: $(shell_escape "$string")"
echo "expanded: $(bash -c "echo $(shell_escape "$string")")"
PS 항상 작은 따옴표로 묶인 문자열은 큰 따옴표로 묶은 문자열보다 간단하기 때문에 인코딩합니다.
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"
}
'
내부 따옴표를 허용합니다 '
. 다음과 같이 사용하십시오.
$ 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"'
작은 따옴표 안에 올바르게 인용 된 모든 문자열.
분명히 큰 따옴표로 묶는 것이 더 쉬울 것입니다. 그러나 그 문제는 어디에 있습니까? 다음은 작은 따옴표 만 사용하는 대답입니다. 대신 변수를 사용하고 alias
있으므로 증명을 위해 인쇄하기가 더 쉽지만 alias
.
$ rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'
$ echo $rxvt
urxvt -fg '#111111' -bg '#111111'
설명
핵심은 작은 따옴표를 닫고 원하는만큼 여러 번 다시 열 수 있다는 것입니다. 예를 들어 foo='a''b'
동일하다 foo='ab'
. 따라서 작은 따옴표를 닫고 리터럴 작은 따옴표 \'
를 넣은 다음 다음 작은 따옴표를 다시 열 수 있습니다.
고장 다이어그램
이 다이어그램은 괄호를 사용하여 작은 따옴표가 열리고 닫히는 위치를 표시하여 명확하게합니다. 인용 부호는 괄호처럼 "중첩"되지 않습니다. 올바르게 적용된 색상 강조 표시에도주의를 기울일 수 있습니다. 인용 된 문자열은 적갈색이고은 \'
검정색입니다.
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\' # original
[^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^ # show open/close quotes
urxvt -fg ' #111111 ' -bg ' #111111 ' # literal characters remaining
(이것은 본질적으로 Adrian과 동일한 대답이지만 이것이 더 잘 설명한다고 생각합니다. 또한 그의 대답에는 끝에 2 개의 불필요한 작은 따옴표가 있습니다.)
여기 또 다른 해결책이 있습니다. 이 함수는 위의 투표 된 답변이 설명하는 것처럼 단일 인수를 취하고 작은 따옴표 문자를 사용하여 적절하게 인용합니다.
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'
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!'
참고 URL : https://stackoverflow.com/questions/1250079/how-to-escape-single-quotes-within-single-quoted-strings
'program story' 카테고리의 다른 글
pip install mysql-python이 EnvironmentError와 함께 실패 : mysql_config not found (0) | 2020.09.29 |
---|---|
git pull 실행 취소, 저장소를 이전 상태로 가져 오는 방법 (0) | 2020.09.28 |
zlib, gzip 및 zip은 어떤 관련이 있습니까? (0) | 2020.09.28 |
유효한 이메일 주소의 최대 길이는 얼마입니까? (0) | 2020.09.28 |
HashMap, LinkedHashMap 및 TreeMap의 차이점 (0) | 2020.09.28 |