Bash는 작은 따옴표 안의 특수 문자를 해석합니다.

Bash는 작은 따옴표 안의 특수 문자를 해석합니다.

예상치 못했지만 흥미로운 동작이 발생했습니다. 다소 복잡한 실행을 하던 중 Bash가 문자를 처리하는 방식에 대한 이해를 토대로 해서는 안 되는 상황에 직면했습니다.

문제의 작은 예:

$ arr=( "$(echo '1 && !/==/')" )
-bash: !/=: event not found

여기서 무슨 일이 일어나고 있는 걸까요? 내가 이해한 바에 따르면, 작은 따옴표는 Bash가 어떤 종류의 확장 없이 모든 문자를 문자 그대로 해석하도록 강제하는 것으로 간주됩니다.

배시 사용하기 4.1.2.

편집: 단순화된 복사 문제.

답변1

bash는 잘못된 이벤트에 대한 오류와 함께 종료됩니다.

!당신은 두려운 기록 대체( 큰따옴표 안의 문자) 로 인해 막혔습니다 . 를 사용하여 비활성화할 수 있습니다 set +H. 그건 그렇고, 이것은 스크립트에서 발생하지 않습니다.

readarray단어 분할과 관련하여 (또는 별칭 mapfile) 을 사용할 수 있습니다.

readarray -t array < <(df -Ph ...)

답변2

더 작은 예(그러나 작지는 않을 것임)동부 시간), Bash 4.1에서:

$ set -H
$ arr=( "$(echo '1 && !/==/' )" )
bash4.1: !/==/': event not found
$ arr=(  $(echo '1 && !/==/' )  )              # no error
$ 

배쉬 4.4에서:

$ set -H
$ arr=( "$(echo '1 && !/==/' )" )              # no error
$ arr=(  $(echo '1 && !/==/' )  )              # no error
$ 

그건역사적 확장좋아요 이는 명령줄 처리 초기에 발생하며 그때까지 전체 명령이 구문 분석되지 않습니다.

히스토리 확장은 전체 행을 읽자마자 수행되며, 그런 다음 쉘에 의해 단어로 나누어 각 행에서 개별적으로 수행됩니다.

왜 이렇게 작동하는지, 왜 큰따옴표가 영향을 미치는지 잘 모르겠지만, 제가 들었던 것으로 기억하는 역사적 확장 관련 버그는 이것만이 아닙니다.

set +H기록 확장을 사용하거나 끌 수 set +o histexpand있으며 스크립트에서는 기본적으로 활성화되지 않습니다.

또한 Bash 4.1은 10년이 넘었으며 Bash 4.4(마지막 버전 번호는 4.x)도 2016년에 출시되었습니다. 4.1부터는 기타 버그가 수정되고 유용한 기능이 추가되었습니다.

관련 정보