bash에 느낌표 (!)를 사용할 수 없습니까?


86

curl 명령을 사용하여 !경로에 느낌표 ( )가 있는 http URL에 액세스하려고 합니다. 예 :

curl -v "http://example.org/!287s87asdjh2/somepath/someresource"

콘솔은로 응답합니다 bash: ... event not found.

무슨 일이야? 느낌표를 피하기위한 적절한 구문은 무엇입니까?


bash 4.4 이상에서 해결
Isaac

답변:


98

느낌표는 bash에서 히스토리 확장의 일부입니다. 그것을 사용하려면 작은 따옴표 (예 :)로 묶 'http://example.org/!132'거나 \문자 앞에 백 슬래시 ( ) 로 직접 이스케이프해야 합니다 (예 :) "http://example.org/\!132".

큰 따옴표에서 느낌표 앞의 백 슬래시는 기록 확장을 방지하지만 이러한 경우 백 슬래시는 제거되지 않습니다. 따라서 작은 따옴표를 사용하는 것이 좋습니다 curl. 따라서 URL의 일부로 리터럴 백 슬래시를 전달하지 않습니다 .


8
"http://example.org/\!132"실제로 백 슬래시를 해석하지 않고 확장합니다 (POSIX 준수 이유, 나는 믿습니다).
Chris Down

@ChrisDown, 텍스트에서 두 번째 옵션이라는 것을 분명히하려고했습니다. 혼란의 가능성을 지적 해 주셔서 감사합니다.
Daniel Pittman

6
기록을 위해 : "!"를 빠져 나가는 것은 이식성이 없습니다. 가장 좋은 방법은 항상 "!"를 인용하는 것입니다. 관련 : "^"(캐럿)은 이식성을 위해 인용해야하는 메타가 아닌 문자입니다. 드디어, "!" if 문에 사용해서는 안됩니다. 가능하면 대신 테스트 할 인수로 사용하십시오 (Solaris / bin / sh로 인해).
Nicholas Wilson

5
작은 따옴표 만 나를 위해 일했습니다. zsh는 여전히 해석 \!하고 큰 따옴표를 사용했습니다.
orkoden

1
Solaris (오래된 이전 XPG4 쉘 폐기)에서 '^'은 별명이며 |파이프를 작성하는 데 사용됩니다. 고객에게 스크립트를 보내는데 어떤 쉘을 실행할 것인지 확신 할 수 없다면 모두 테스트해야합니다!
Nicholas Wilson

61

Daniel이 제공 한 답변뿐만 아니라와 함께 사용하지 않는 경우 내역 확장을 사용 중지 할 수도 있습니다 set +H.


19
역사 확장을 완전히 끄는 것이 하루 종일 들었던 최고의 조언입니다! 역사 확장은 위험하고 있습니다 비잔틴 있을 때 더 나은 대안 (증분 역사를 검색 Ctrl-R하면 미리보기 및 당신이 맹목적으로 명령을 멀리 발생하지 않도록 명령을 편집 할 수) !-14당신이 생각에 있었다 !-12, 죄송합니다, 우연히 그 rm -rf *. 안전한. 히스토리 확장 사용 안함! 에쉬 !!
aculich

6
가장 큰 대답 : 기록 확장은 큰 보안 위험입니다! 제작 된 URL을 통해 유닉스를 공격하는 데 사용할 수 있습니다.
dan

@aculich 또는 POSIX 지정 명령을 fc -14대신 사용하십시오. 그러나 히스토리 확장을 사용하지 않고도 할 수 있다는 것이 사실입니다. 개인적으로, 나는 사용 !$하고 !vi그리고 sudo !!심지어 git add !vi:$자주 역사 확장이 가능 떠나 보증 할 수 있습니다.
와일드 카드

나는 이것을 쉘 RC 파일에 추가 할 것이라고 생각한다. 나는 이것을 단정 한 "트릭"으로 만 사용했습니다
TonyH

17

나는 작은 따옴표를 개인적으로 할 것이나, 완전성, 나는 또한이 URL이기 때문에, 당신은 인코딩 할 수 있습니다 것 !등을 %21예를 들어, curl -v http://example.org/%21132.


13

이것은 또한 할 수 있습니다

curl -v "http://example.org/"'!'"287s87asdjh2/somepath/someresource"
또는
curl -v "http://example.org/"\!"287s87asdjh2/somepath/someresource"

bash는 인접한 문자열을 연결하기 때문에 작동합니다. 이 방법은 쉘 확장이 필요한 다른 것들이있을 때 특히 유용하므로 전체 문자열에 작은 따옴표를 사용할 수 없습니다 :

curl -v 'http://example.org/!'"287s87asdjh2/${basepath}/someresource"

!문자는 명령 행 프롬프트에서 히스토리 확장에 사용됩니다.
따라서 이것은 프롬프트에서는 문제가 될 수 있지만 쉘 스크립트 파일에서는 문제가되지 않습니다.
역사 확장은 큰 따옴표로도 작동합니다.


유닉스 명령어와 영어 문장이 필요한 것보다 많은 문자를 사용하고 필요한 것보다 더 혼란스럽게 만드는 많은 방법이 있습니다. 첫 번째 / 허용 / 투표 된 답변보다 전체 URL을 작은 따옴표로 묶는 것보다 어떻게 우수합니까?
G-Man

2
@ G-Man : bash 인수를 구성하는 다른 방법을 알려줍니다. 이 방법을 몰랐습니다. 새로운 것을 배우는 데 아무런 문제가 없습니다.
Sahil Singh

@SahilSingh 이것은 어떻게 새로운가? 큰 따옴표로 묶인 문자열 하나와 작은 따옴표로 묶인 문자열 세 개를 연결합니다. 여기에 중첩이 없습니다.
Raphael

@ G-Man 두 줄을 나란히 놓을 때 연결되는 것은 분명하지 않습니다. printf ( "hello" "world")는 c에서도 작동하지만 printf ( "hello" 'w')는 작동하지 않으므로 bash가 그러한 표현을 수용한다는 것은 새로운 것이지만 나는 동의합니다. 유틸리티 관점에서 이것은 우수하지 않습니다. 나는 대답을 좋아했고 Mark Shust도 그렇습니다.
Sahil Singh

2
하나가 다른 문자열 확장이있는 경우 @ G-남자는 또한 유용 않습니다 같은 문자열에서 발생 할이. 이것은 두 가지 유형의 인용 동작을 분리하는 쉬운 방법입니다.
WAF

7

나는 같은 문제를 겪었고 간단한 해결책은 변수를 사용하는 것이 었습니다.

E=!  
curl -v "http://example.org/${E}287s87asdjh2/somepath/someresource"

여기서 간단 함은 (1) 쉘과 명령에서 이식 가능합니다. (2) 이스케이프 구문과 ASCII 코드를 알 필요가 없습니다.


3

Bash 4.3 이후로 이제 큰 따옴표를 사용하여 내역 확장 문자를 인용 할 수 있습니다.

$ bash --version
GNU bash, version 4.3...
[...]
$ echo "Hello World!"
Hello World!

이외이 나던 작품은 echo, 에코 다르게 자체적으로이 문제를 해결할 것
phil294

@Blauhirn 이것은 echo와 관련이 없으며 인용과 관련이 있으며 실행중인 bash 버전과 관련이 있습니다.
Flimm

2
이 답변은 잘못되었으므로 삭제해야합니다. 당신의 bash버전은 확장되지 않은 뱅과 아무런 관련이 없으며, 이는 예제에서 !"줄 끝"이 뒤 따르고 쉘이 확장하려고 시도하지 않기 때문입니다. 시도 하면 답장을 echo "!Hello World"볼 수 있습니다. 자세한 내용은 매뉴얼을 참조하십시오bashbash: !Hello: event not found
don_crissti

0

Windows에서 git bash를 사용하는 사람들에게는 @DanielPittman의 대답이 작동합니다. 그러나 백 슬래시 (\)를 슬래시 (/)로 바꾸어야합니다.

예를 들어, 유닉스에서는 다음과 같이 보일 것입니다.

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS\!ZR412543s'

Windows의 경우 다음과 같습니다 (권한 헤더 부분의 슬래시에 초점)

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS/!ZR412543s'


이것은 말이되지 않습니다. 작은 따옴표로 묶은 인수가 있으므로 느낌표와 관련된 슬래시와 상관없이 기록이 확장되지 않습니다.
와일드 카드

오 네 말이 맞아 Daniel의 답변 (백 슬래시 사용)을 사용할 때 오류가 발생하기 때문에이 답변 만 게시했습니다.
SamuelDev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.