!
명령줄 기록의 맥락에서 이것이 명령줄에 특별한 의미가 있다는 것을 알고 있지만 , 그 외에도 느낌표는 때때로 스크립트 실행 시 구문 분석 오류를 일으킬 수 있습니다.
a와 관련이 있는 것 같은데 event
a가 무엇인지 모르겠습니다.이벤트그것이 무엇인지, 무엇을 하는지. 그럼에도 불구하고 동일한 명령이 상황에 따라 다르게 작동할 수 있습니다.
아래의 마지막 예에서는 오류가 발생하지만 동일한 코드가 명령 대체 외부에서 작동할 때 왜 작동합니까? ..GNU bash 4.1.5 사용
# This works, with or without a space between ! and p
{ echo -e "foo\nbar" | sed -nre '/foo/! p'
echo -e "foo\nbar" | sed -nre '/foo/!p'; }
# bar
# bar
# This works, works when there is a space between ! and p
var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"
# bar
# This causes an ERROR, with NO space between ! and p
var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"
# bash: !p': event not found
답변1
이 !
역할은 bash의 기록 대체를 호출합니다(대화형 셸에서 기본적으로 활성화됨). 실패한 예에서와 같이 문자열이 뒤에 오면 해당 문자열로 시작하는 마지막 기록 이벤트로 확장을 시도합니다. 마치 $var
이 문자열의 값을 확장하면 !echo
기록의 마지막 echo 명령까지 확장됩니다.
공간은 이러한 확장에서 파괴적인 기능입니다. 먼저 이것이 변수를 어떻게 처리하는지 살펴보세요.
# var="like"
# echo "$var"
like
# echo "$"
$
# echo "Do you $var frogs?"
Do you like frogs? <- as expected, variable name broken at space
# echo "Do you $varfrogs?"
Do you? <- $varfrogs not defined, replaced with blank
# echo "Do you $ var frogs?"
Do you $ var frogs? <- $ not a valid variable name, ignored
역사 확장에서도 같은 일이 일어납니다. 느낌표( !
)는 기록 대체 시퀀스를 시작하지만 뒤에 문자열이 오는 경우에만 해당됩니다. 교체 시퀀스의 일부가 아닌 문자 그대로의 폭발을 만들려면 공백을 추가하세요.
작은따옴표를 사용하면 이러한 변수 대체 및 기록 확장을 방지할 수 있습니다. 첫 번째 예에서는 작은따옴표를 사용하므로 제대로 작동합니다. 마지막 예는 큰따옴표로 묶여 있으므로 bash는 다른 작업을 수행하기 전에 확장 시퀀스를 검색합니다. 첫 번째가 트립되지 않는 유일한 이유는 위에 표시된 것처럼 공백이 깨지는 문자이기 때문입니다.
답변2
이미케일럽 라고, !
bash의 기록 교체를 호출하는 데 사용됩니다.
나처럼 그러한 기능이 필요하지 않다고 생각되면 다음 줄을 삽입하여 기능을 비활성화할 수 있습니다 ~/.bashrc
.
set +H
위쪽 화살표 및 -증분 역방향 검색으로 기록을 복원할 수 있기 때문에 필요하지 않습니다 Ctrl. rbash의 매뉴얼 페이지 섹션을 참조하십시오.기록을 조작하는 명령자세한 단축키 목록에 대해 알아보세요.
답변3
첫 번째 예:
{ echo -e "foo\nbar" | sed -nre '/foo/! p'
echo -e "foo\nbar" | sed -nre '/foo/!p'; }
로 줄일 수 있습니다
echo '! p'
echo '!p'
작은따옴표 내에서 모든 문자는 리터럴 값을 유지합니다. 그 결과 !
그 특별한 의미를 상실하였고, 역사의 전개도 진행되지 않았다.
두 번째 및 세 번째 예:
var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"
var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"
로 줄일 수 있습니다
echo "'! p'"
echo "'!p'"
'! p'
'!p'
본질적으로 큰따옴표로 묶인 문자열의 일부입니다 .
큰따옴표 안의 모든 문자는 리터럴 값을 유지합니다.와는 별개로 $
, `
, \
그리고 !
.
'! p'
이는 및 에 대한 작은따옴표가 '!p'
특별한 의미를 잃었지만(예: 이스케이프할 수 없음 !
) !
여전히 특별한 의미를 유지하여 역사적 확장을 수행한다는 것을 의미합니다.
그러나 !
뒤에 공백 문자가 오면 히스토리 확장이 수행되지 않습니다.
인용 출처 man bash
:
인용하다
[...]
문자를 작은따옴표로 묶으면 따옴표 안의 각 문자의 리터럴 값이 유지됩니다. [...]
문자를 큰따옴표로 묶으면 기록 확장이 활성화된 경우 $, `, \ 및 !를 제외한 따옴표 안의 모든 문자의 리터럴 값이 유지됩니다. [...] 활성화되면 !가 큰따옴표 안에 표시되고 백슬래시로 이스케이프되지 않는 한 기록 확장이 수행됩니다. ! 앞의 백슬래시는 제거되지 않습니다.
역사적 확장
[...]
역사 확장 캐릭터의 등장을 통해 역사 확장이 소개된다는 것, 즉! 기본적으로. 백슬래시(\)와 작은따옴표만 기록 확장 문자를 인용할 수 있습니다.
뒤에 기록 확장 문자가 오면 따옴표가 없더라도 기록 확장을 억제하는 여러 문자(공백, 탭, 줄 바꿈, 캐리지 리턴 및 =)가 있습니다. (extglob 쉘 옵션이 활성화된 경우 확장도 억제됩니다.