Bash에서 명령에 인수를 지정할 때 어떤 문자를 이스케이프해야합니까?
그들은 배쉬의 메타 문자로 제한됩니다 : 공백, 탭,
|
, &
, ;
, (
, )
, <
,와 >
?
Bash에서 명령에 인수를 지정할 때 어떤 문자를 이스케이프해야합니까?
그들은 배쉬의 메타 문자로 제한됩니다 : 공백, 탭,
|
, &
, ;
, (
, )
, <
,와 >
?
답변:
다음 문자는 일부 상황에서 쉘 자체에 특별한 의미를 가지며 인수에서 이스케이프해야 할 수도 있습니다.
`
백틱 (U + 0060 Grave Accent)~
물결표 (U + 007E)!
느낌표 (U + 0021)#
해시 (U + 0023 숫자 부호)$
달러 기호 (U + 0024)&
앰퍼샌드 (U + 0026)*
별표 (U + 002A)(
왼쪽 괄호 (U + 0028))
오른쪽 괄호 (U + 0029)
( ⇥
) 탭 (U + 0009){
왼쪽 버팀대 (U + 007B 왼쪽 꼬인 브래킷)[
왼쪽 대괄호 (U + 005B)|
세로 막대 (U + 007C 세로선)\
백 슬래시 (U + 005C Reverse Solidus);
세미콜론 (U + 003B)'
작은 따옴표 / 아포스트로피 (U + 0027)"
큰 따옴표 (U + 0022)↩
줄 바꾸기 (U + 000A)<
(U + 003C) 미만>
보다 큼 (U + 003E)?
물음표 (U + 003F)
우주 (U + 0020) 1이 캐릭터들 중 일부는 내가 링크 한 것보다 더 많은 곳에서 더 많은 곳에서 사용됩니다.
명시 적으로 선택적인 몇 가지 경우가 있습니다.
!
set +H
비 대화식 쉘에서는 기본값 인을 사용하여 비활성화 할 수 있습니다 .{
로 비활성화 할 수 있습니다 set +B
.*
와 ?
함께 해제 할 수 있습니다 set -f
또는set -o noglob
.=
set -k
또는set -o keyword
활성화 된 경우 등호 (U + 003D)도 이스케이프해야합니다 .줄 바꿈을 이스케이프 처리 하려면 인용 부호가 필요합니다. 백 슬래시는 작업을 수행하지 않습니다. IFS에 나열된 다른 문자 는 유사한 처리가 필요합니다. 당신은 탈출 할 필요가 없습니다 ]
나 }
,하지만 당신은 않습니다 탈출 할 필요 )
가 연산자이기 때문에.
이러한 캐릭터 중 일부는 다른 캐릭터보다 이스케이프해야하는 경우에 대한 제한이 엄격합니다. 예를 들어, a#b
괜찮지 만 a #b
주석 이지만 >
두 컨텍스트 모두에서 이스케이프해야합니다. 어쨌든 그것들을 보수적으로 탈출하는 것은 아프지 않으며 훌륭한 차이점을 기억하는 것보다 쉽습니다.
명령 이름 자체가 쉘 키워드 인 경우 ( if
, for
, do
) 당신은 탈출하거나 너무 그것을 인용해야합니다. 그 중 유일한 흥미로운 것은입니다 in
. 왜냐하면 그것이 항상 키워드라는 것이 확실하지 않기 때문입니다. 당신은 하지 않습니다 (! 어리석게도)에만했습니다 때, 인수에 사용 된 키워드에 대해 그렇게 할 필요가 그 중 한 후 명령을 지명했다. 셸 연산자 ( (
, &
등)는 항상 어디에 있든지 인용해야합니다.
1 Stéphane은 로케일의 다른 1 바이트 공백 문자 도 이스케이프해야 한다고 언급했습니다 . 가장 일반적이고 합리적인 로케일, 적어도 C 또는 UTF-8을 기반으로하는 로케일은 위의 공백 문자뿐입니다. 일부 ISO-8859-1 로켈에서 Solaris, BSD 및 OS X를 포함하여 U + 00A0 휴식 공간이 비어있는 것으로 간주됩니다 (잘못 생각합니다). 임의의 알 수없는 로케일을 처리하는 경우 문자를 포함하여 거의 모든 것을 포함 할 수 있으므로 행운을 빕니다.
아마도 공백으로 간주되는 단일 바이트는 공백이 아닌 멀티 바이트 문자 내에 나타날 수 있으며 전체를 따옴표로 묶는 것 외에는 탈출 할 수 없습니다. 이것은 이론적 인 문제가 아닙니다. 위에서 ISO-8859-1 로켈에서 A0
공백으로 간주되는 바이트는 UTF-8로 인코딩 된 "à"( ) 와 같은 멀티 바이트 문자 내에 나타날 수 있습니다 C3 A0
. 해당 문자를 안전하게 처리하려면 해당 문자를 인용해야합니다 "à"
. 이 동작은 스크립트를 작성한 환경이 아니라 스크립트를 실행하는 환경의 로케일 구성에 따라 다릅니다.
나는이 행동이 여러 가지 방법으로 망가 졌다고 생각하지만, 우리는 우리가 다루는 손을 대해야한다. 자체 동기화되지 않는 멀티 바이트 문자 세트로 작업하는 경우 가장 안전한 것은 모든 것을 인용하는 것입니다. UTF-8 또는 C 인 경우 안전합니다 (현재).
!
csh 히스토리 확장이 사용 가능한 경우 에만 일반적으로 스크립트가 아닌 이스케이프 하면됩니다. [ ! -f a ]
또는 find . ! -name...
괜찮습니다. 그것은 당신의 더 엄격한 한계 섹션 에서 다뤄지지 만 명시 적으로 언급 할 가치가 있습니다.
hash[foo"]"]=
, ${var-foo"}"}
, [[ "!" = b ]]
, [[ a = "]]" ]]
,에 대한 정규 표현식 연산자 [[ x =~ ".+[" ]]
. 이외의 키워드 {
( if
, while
, for
그들이 같은 인식하지 않을 수 있도록 ...) ... 인용 될 필요가있을 것이다
]
), 나는 그것들을 나열하지 않습니다. 인수 위치에 키워드를 인용해야한다고 생각하지 않습니다.
GNU Parallel에서 이것은 테스트되고 광범위하게 사용됩니다 :
$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'
$a =~ s/[\n]/'\n'/go;
그것은에서 테스트되어 bash
, dash
, ash
, ksh
, zsh
,와 fish
. 일부 문자는 일부 (버전) 쉘에서 인용 할 필요는 없지만 위의 모든 테스트 된 쉘에서 작동합니다.
단순히 따옴표로 묶은 문자열을 원하면 다음과 같이 파이프로 묶을 수 있습니다 parallel --shellquote
.
printf "&*\t*!" | parallel --shellquote
Perl의 경량 이스케이프 솔루션의 경우 작은 따옴표 원칙을 따르고 있습니다. 작은 따옴표로 묶인 Bash-string은 작은 따옴표 자체를 제외한 모든 문자를 가질 수 있습니다.
내 코드 :
my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";
} else {
print $_;
}
}
예제 실행 1 :
$ echo -n "abc" | perl escape_bash_special_chars.pl
abc
예제 실행 2 :
echo "abc" | perl escape_bash_special_chars.pl
'abc
'
예제 실행 3 :
echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c
예제 실행 4 :
echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'
예제 실행 5 :
echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'
echo 'ab'"'"'c'
ab'c