[bash] bash에서 와일드 카드 / 별표 문자를 어떻게 피할 수 있습니까?

예를 들면 다음과 같습니다.

me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR

그리고 사용하여 \이스케이프 문자를 :

me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR

분명히 바보 같은 짓을하고 있습니다.

출력은 어떻게 얻 BAR * BAR습니까?



답변

설정 $FOO이 충분하지 않을 때 인용 . 변수 참조도 인용해야합니다.

me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR


답변

짧은 답변

다른 사람들이 말했듯이 이상한 행동을 막기 위해 항상 변수를 인용해야합니다. 사용 그래서 “$ foo는”에코 대신에 단지 $ foo는 에코 .

긴 대답

나는이 예가 그 얼굴에 보이는 것보다 더 많은 일이 있기 때문에 더 많은 설명이 필요하다고 생각합니다.

첫 번째 예제를 실행 한 후 쉘이 분명히하고 있다고 생각했기 때문에 혼란이 어디에서 발생했는지 알 수 있습니다.

  1. 파라미터 확장
  2. 파일 이름 확장

첫 번째 예에서 :

me$ FOO="BAR * BAR"
me$ echo $FOO

매개 변수 확장 후는 다음과 같습니다.

me$ echo BAR * BAR

그리고 파일 이름 확장 후 다음과 같습니다.

me$ echo BAR file1 file2 file3 file4 BAR

그리고 echo BAR * BAR명령 행에 입력하면 그것들이 동등한 것을 볼 수 있습니다.

“*를 피하면 파일 이름 확장을 막을 수 있습니다.”

두 번째 예에서 :

me$ FOO="BAR \* BAR"
me$ echo $FOO

매개 변수 확장 후는 다음과 같아야합니다.

me$ echo BAR \* BAR

파일 이름 확장 후 다음과 같아야합니다.

me$ echo BAR \* BAR

명령 행에 “echo BAR \ * BAR”을 직접 입력하면 이스케이프로 파일 이름 확장이 방지되므로 실제로 “BAR * BAR”이 인쇄됩니다.

그렇다면 왜 $ foo를 사용할 수 없었습니까?

견적 제거라는 세 번째 확장이 있기 때문입니다. bash 수동 따옴표 제거는 다음과 같습니다.

앞의 확장 후에는 위의 확장 중 하나에서 발생하지 않은 인용되지 않은 문자 ‘\’, ” ‘및’ ” ‘가 모두 제거됩니다.

따라서 명령 행에 명령을 직접 입력하면 이스케이프 문자는 이전 확장의 결과가 아니므로 에코 명령으로 보내기 전에 BASH가이를 제거하지만 두 번째 예에서는 “\ *” 이전 매개 변수 확장의 결과이므로 제거되지 않습니다. 결과적으로 echo는 “\ *”를 수신하고 인쇄됩니다.

첫 번째 예의 차이점- “*”는 따옴표 제거로 제거 될 문자에 포함되지 않습니다.

이것이 의미가 있기를 바랍니다. 결국 같은 결론-따옴표 만 사용하십시오. 방금 매개 변수 및 파일 이름 확장 만 작동하는 경우 논리적으로 작동 해야하는 탈출이 작동하지 않는 이유를 설명하려고 생각했습니다.

BASH 확장에 대한 자세한 설명은 다음을 참조하십시오.

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions


답변

이 오래된 스레드에 약간을 추가하겠습니다.

보통은

$ echo "$FOO"

그러나이 구문에도 문제가 있습니다. 다음 스크립트를 고려하십시오.

#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"

*그대로 전달해야 curl하지만 같은 문제가 발생합니다. 위의 예제는 작동하지 않으며 (현재 디렉토리의 파일 이름으로 확장됩니다) 어느 것도 작동하지 않습니다 \*. 또한 $curl_opts단일 (유효하지 않은) 옵션으로 인식되므로 인용 할 수 없습니다 curl.

curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information

따라서 전역 패턴에 적용하거나 내장 플래그를 사용하는 경우 파일 이름 확장을 방지하기 위해 bash변수 $GLOBIGNORE를 사용하는 것이 좋습니다 set -f.

#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"  ## no filename expansion

원래 예제에 적용 :

me$ FOO="BAR * BAR"

me$ echo $FOO
BAR file1 file2 file3 file4 BAR

me$ set -f
me$ echo $FOO
BAR * BAR

me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR


답변

FOO='BAR * BAR'
echo "$FOO"


답변

echo "$FOO"


답변

printf오히려 사용 습관을들이는 것이 좋습니다.echo커맨드 라인 .

이 예제에서는 많은 이점을 제공하지 않지만 더 복잡한 출력으로 더 유용 할 수 있습니다.

FOO="BAR * BAR"
printf %s "$FOO"


답변