Bash에서 명령에 명령줄 인수를 지정할 때 어떤 문자를 이스케이프해야 합니까?
|
Bash의 메타 문자인 공백, 탭 , , , , , , 및 으로 제한됩니까 ?&
;
(
)
<
>
답변1
일부 상황에서 다음 문자는 셸 자체에 특별한 의미를 가지며 매개변수에서 이스케이프해야 할 수도 있습니다.
특징 | 유니코드 | 이름 | 용법 |
---|---|---|---|
` |
U+0060(악센트) | 백틱 | 명령 대체 |
~ |
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 역고상선 | 백슬래시 | 이스케이프 문자 |
; |
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
.=
다음과 같은 경우 등호(U+003D)도 이스케이프해야 합니다.set -k
또는set -o keyword
활성화되었습니다.
개행 문자 이스케이프인용이 필요합니다— 백슬래시는 효과가 없습니다. 에 나열된 다른 문자IFS유사한 처리가 필요합니다. 탈출 ]
하거나 을 할 필요 }
는 없지만하다)
연산자이므로 이스케이프해야 합니다 .
이러한 문자 중 일부는 실제로 탈출해야 할 때 다른 문자보다 더 엄격한 제한을 적용합니다. 예를 들어, a#b
괜찮지만 a #b
주석이므로 >
두 경우 모두 이스케이프가 필요합니다. 그럼에도 불구하고 보수적으로 피하는 것이 나쁠 것은 없으며 미묘한 차이점을 기억하는 것보다 쉽습니다.
명령 이름 자체가 셸 키워드( if
, for
, do
)인 경우 해당 키워드도 이스케이프하거나 인용해야 합니다. 유일하게 흥미로운 점은 in
항상 키워드이기 때문에 명확하지 않다는 것입니다. 너아니요(어리석게도!) 이러한 키워드 중 하나의 이름을 따서 명령 이름을 지정한 경우 인수에 사용된 키워드에 대해서만 이 작업을 수행하면 됩니다. 쉘 연산자( (
등 &
)는 사용될 때마다 항상 인용이 필요합니다.
1 스테판은 다른 점을 지적합니다.단일 바이트해당 지역의 공백 문자탈출도 필요합니다. 가장 일반적이고 합리적인 로케일(적어도 C 또는 UTF-8 기반의 로케일)에서는 위의 공백 문자일 뿐입니다. U+00A0 줄바꿈 없는 공백은 Solaris, BSD 및 OS X를 포함한 일부 ISO-8859-1 로케일에서 공백으로 처리됩니다(제 생각에는 잘못된 것 같습니다). 알 수 없는 로케일을 다루는 경우 문자를 포함한 모든 것이 포함될 수 있으므로 행운을 빕니다.
공백으로 간주되는 단일 바이트가 있을 수 있다고 생각할 수 있습니다.이내에공백이 아닌 멀티바이트 문자이므로 전체 문자를 따옴표로 묶는 것 외에는 이스케이프할 수 있는 방법이 없습니다. 이는 이론적인 문제가 아닙니다. 위의 ISO-8859-1 로케일에는 A0
공백으로 처리되는 바이트가 있을 수 있습니다.이내에UTF-8로 인코딩된 "à"( )와 같은 멀티바이트 문자입니다 C3 A0
. 이러한 문자를 안전하게 처리하려면 해당 문자를 인용해야 합니다 "à"
. 이 동작은 스크립트를 작성하는 환경의 로케일 구성이 아니라 스크립트가 실행되는 환경의 로케일 구성에 따라 달라집니다.
나는 이 행동이 여러 가지 방법으로 깨질 수 있다고 생각하지만, 우리는 주어진 카드를 가지고 놀아야 합니다. 자체 동기화되지 않는 멀티바이트 문자 집합을 사용하는 경우 가장 안전한 방법은 모든 항목을 인용하는 것입니다. UTF-8이나 C를 사용하면 (현재로서는) 안전합니다.
답변2
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
답변3
Perl의 경량 이스케이프 솔루션의 경우 작은따옴표 원칙을 따릅니다. 작은따옴표 안의 Bash 문자열에는 작은따옴표 자체를 제외한 모든 문자가 포함될 수 있습니다.
내 코드:
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