명령 행 인수에서 이스케이프하려면 어떤 문자가 필요합니까?


14

Bash에서 명령에 인수를 지정할 때 어떤 문자를 이스케이프해야합니까?

그들은 배쉬의 메타 문자로 제한됩니다 : 공백, 탭, |, &, ;, (, ), <,와 >?


* 및?로 파일 이름을 붙입니다 (가능한).
Jeff Schaller

감사. cmd line args에서 이스케이프 해야하는 문자 종류를 철저히 나열 할 수 있습니까?
Tim

이 목록은 가지고 있지만 인용에 대해 가장 중요하게 이해해야 할 것은 다음과 같습니다. 작은 따옴표 사이의 모든 것은 문자 그대로 단어 분리없이 전달됩니다. 예외 없음. (이것은 작은 따옴표 안에 작은 따옴표를 포함시키는 방법이 없다는 것을 의미하지만, 해결하기 쉽습니다 .)
Wildcard

답변:


22

다음 문자는 일부 상황에서 쉘 자체에 특별한 의미를 가지며 인수에서 이스케이프해야 할 수도 있습니다.

이 캐릭터들 중 일부는 내가 링크 한 것보다 더 많은 곳에서 더 많은 곳에서 사용됩니다.


명시 적으로 선택적인 몇 가지 경우가 있습니다.

  • !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 인 경우 안전합니다 (현재).


로케일의 다른 공백도 이스케이프해야합니다 ( 버그로 인해 현재 멀티 바이트를 제외하고 )
Stéphane Chazelas

!csh 히스토리 확장이 사용 가능한 경우 에만 일반적으로 스크립트가 아닌 이스케이프 하면됩니다. [ ! -f a ]또는 find . ! -name...괜찮습니다. 그것은 당신의 더 엄격한 한계 섹션 에서 다뤄지지 만 명시 적으로 언급 할 가치가 있습니다.
Stéphane Chazelas

다른 문자처럼 인용 필요 컨텍스트가하는 것으로 : hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]],에 대한 정규 표현식 연산자 [[ x =~ ".+[" ]]. 이외의 키워드 {( if, while, for그들이 같은 인식하지 않을 수 있도록 ...) ... 인용 될 필요가있을 것이다
스테판 Chazelas가에게

그것들이 전혀 명령 줄 인수 인 한, 해석은 문제의 명령에 달려 있습니다 (와 마찬가지로 ]), 나는 그것들을 나열하지 않습니다. 인수 위치에 키워드를 인용해야한다고 생각하지 않습니다.
Michael Homer

2
내장, 대시 또는 %를 인용해도 아무런 효과가 없습니다.
Michael Homer

3

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

내가 어떻게 평행을 들어 보지 못했는지 ...
Tom H

@TomH 5 분 동안 귀하에게 도달 할 수있는 방법을 생각하면 감사하겠습니다.
Ole Tange

진행 문제라고 생각합니다. 대부분의 사람들은 복잡한 단계를 거치기 전까지는 병렬을 필요로하거나 이해하지 않아도됩니다. 그때까지 그들은 xargs, nohup 및 그런 것들을 만났습니다. 또한 병렬 교환을 사용하여 스택 교환에서 문제를 해결하거나 Google에서 문제를 bash로 해결할 솔루션을 찾는 경우가 많지 않습니다.
Tom H

1

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

예, 유효합니다. 제 생각에는 대부분의 사람들이이 페이지에 착륙 할 것입니다. 해결해야 할 문제가 있기 때문입니다. 이것이 흥미로운 학문적 논쟁을 일으키기 때문이 아닙니다. 그렇기 때문에 주제를 약간 벗어난 상태에서도 솔루션을 제공하고 그 장점을 논의하고자합니다.
Jari Turkia

내 코드는 Michael Homer의 답변을 구현 한 것입니다. 나는 그가 한 것보다 더 많은 정보를 가지고 싶지 않았습니다.
Jari Turkia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.