문제

예.

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 명령으로 보내기 전에 제거하지만 두 번째 예에서는 "\*"가 이전 매개변수 확장의 결과이므로 제거되지 않습니다.결과적으로 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"
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top