[bash] Bash의 명령에서 작은 따옴표 안의 변수 확장

작은 따옴표와 작은 따옴표 안에있는 다른 명령과 변수가 있는 bash 스크립트 에서 명령을 실행하고 싶습니다 .

예 : repo forall -c '....$variable'

이 형식에서는 $이스케이프되고 변수가 확장되지 않습니다.

다음 변형을 시도했지만 거부되었습니다.

repo forall -c '...."$variable" '

repo forall -c " '....$variable' "

" repo forall -c '....$variable' "

repo forall -c "'" ....$variable "'"

변수 대신 값을 대체하면 명령이 정상적으로 실행됩니다.

내가 어디로 잘못 가고 있는지 알려주세요.



답변

작은 따옴표 안에는 예외없이 모든 것이 그대로 유지됩니다.

즉, 따옴표를 닫고 무언가를 삽입 한 다음 다시 입력해야합니다.

'before'"$variable"'after'
'before'"'"'after'
'before'\''after'

단어 연결은 단순히 병렬로 수행됩니다. 확인할 수 있듯이 위의 각 줄은 셸에 대한 단일 단어입니다. 따옴표 (상황에 따라 단일 또는 큰 따옴표)는 단어를 분리하지 않습니다. 그들은 단지 공백과 같은 다양한 특수 문자를 사용하지 않도록 해석에 사용된다 $, ;… 인용에 좋은 자습서는 마크 리드의 답변을 참조하십시오. 또한 관련 : bash에서 어떤 문자를 이스케이프해야합니까?

쉘이 해석 한 문자열을 연결하지 마십시오

변수를 연결하여 쉘 명령을 작성하지 마십시오. 이것은 SQL 조각 연결 (SQL injection!)과 유사한 나쁜 생각입니다.

일반적으로 명령에 자리 표시자를두고 호출자가 호출 인수 목록에서이를 수신 할 수 있도록 변수와 함께 명령을 제공 할 수 있습니다.

예를 들어, 다음은 매우 안전하지 않습니다. 이러지마

script="echo \"Argument 1 is: $myvar\""
/bin/sh -c "$script"

내용을 $myvar신뢰할 수없는 경우 다음과 같은 익스플로잇이 있습니다.

myvar='foo"; echo "you were hacked'

위의 호출 대신 위치 인수를 사용하십시오. 다음과 같은 호출이 더 좋습니다. 이용할 수 없습니다.

script='echo "arg 1 is: $1"'
/bin/sh -c "$script" -- "$myvar"

에 할당 할 때 단일 진드기를 사용 script한다는 점에 유의하십시오. 즉, 변수 확장이나 다른 형태의 해석없이 문자 그대로 사용됩니다.


답변

repo명령은 어떤 종류의 따옴표를 가져도 상관 없습니다. 매개 변수 확장이 필요한 경우 큰 따옴표를 사용하십시오. 만약 당신이 많은 것을 백 슬래시해야하는 것을 의미한다면, 대부분의 경우 작은 따옴표를 사용한 다음, 그것들을 나누고 확장이 필요한 부분에 대해 두 배로 들어갑니다.

repo forall -c 'literal stuff goes here; '"stuff with $parameters here"' more literal stuff'

관심이 있다면 설명이 이어집니다.

쉘에서 명령을 실행할 때 해당 명령이 인수로받는 것은 null로 끝나는 문자열의 배열입니다. 이러한 문자열은 절대적으로 포함 할 수 있는 null 이외의 문자를.

그러나 쉘이 명령 행에서 문자열 배열을 작성할 때 일부 문자를 특수하게 해석합니다. 이것은 명령을보다 쉽게 ​​입력 할 수 있도록 설계되었습니다. 예를 들어, 공백은 일반적으로 배열에서 문자열 사이의 경계를 나타냅니다. 이런 이유로 개별 논쟁은 때때로 “단어”라고 불립니다. 그럼에도 불구하고 논쟁에는 공백이있을 수있다. 쉘에 원하는 것을 알려주는 방법이 필요합니다.

문자 (공백 또는 다른 백 슬래시 포함) 앞에 백 슬래시를 사용하여 해당 문자를 문자 그대로 처리하도록 쉘에 지시 할 수 있습니다. 그러나 다음과 같이 할 수 있습니다.

echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier

… 불쾌 할 수 있습니다. 따라서 쉘은 대체 인용 부호를 제공합니다. 이들은 두 가지 주요 품종으로 제공됩니다.

큰 따옴표는 “그룹 따옴표”라고합니다. 와일드 카드와 별칭이 확장되는 것을 방지하지만 대부분 단어에 공백을 포함하기위한 것입니다. 매개 변수 및 명령 확장 (으로 표시되는 종류)과 같은 다른 것들이 $여전히 발생합니다. 물론 큰 따옴표 안에 리터럴 큰 따옴표를 원한다면 백 슬래시해야합니다.

echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"

작은 따옴표는 좀 더 드라코 니안입니다. 그들 사이의 모든 것은 백 슬래시를 포함하여 문자 그대로 완전히 취해집니다. 작은 따옴표 안에 리터럴 작은 따옴표를 얻는 방법은 절대 없습니다.

다행스럽게도 쉘의 인용 부호는 단어 분리 문자가 아닙니다 . 그들 스스로는 단어를 끝내지 않습니다. 동일한 단어 내에서 다른 유형의 따옴표 사이를 포함하여 따옴표를 입력하거나 사용하여 원하는 결과를 얻을 수 있습니다.

echo '"Thank you. That'\''ll be $4.96, please," said the cashier'

따라서 한 쌍의 인용 부호, 백 슬래시 리터럴 단일 인용 부호, 열린 단일 인용 부호 시퀀스에 익숙해지는 데 시간이 많이 걸리지 만 훨씬 쉽습니다.

현대 쉘은 POSIX 표준에 의해 지정되지 않은 다른 인용 스타일을 추가했으며, 앞에 작은 따옴표 앞에 달러 기호가 붙습니다. 인용 된 문자열은 ANSI C 프로그래밍 언어의 문자열 리터럴과 유사한 규칙을 따르므로 “ANSI 문자열”및 $''“ANSI 인용”쌍 이라고도 합니다. 이러한 문자열 내에서 백 슬래시에 대한 위의 조언은 더 이상 적용되지 않습니다. 대신, 다시 특수화됩니다. 역 슬래시를 앞에 추가하여 리터럴 작은 따옴표 나 백 슬래시를 포함시킬 수있을뿐만 아니라 쉘은 ANSI C 문자 이스케이프를 확장합니다 ( \n줄 바꾸기, \t탭 및 \xHH문자 포함). 16 진 코드HH). 그렇지 않으면 작은 따옴표로 묶인 문자열로 작동합니다. 매개 변수 또는 명령 대체가 발생하지 않습니다.

echo $'"Thank you.  That\'ll be $4.96, please," said the cashier'

주목해야 할 것은 echo명령에 대한 인수로 수신 된 단일 문자열 이이 모든 예에서 정확히 동일 하다는 것 입니다. 쉘이 명령 행을 구문 분석 한 후에는 명령이 실행 된 방법을 알 수있는 방법이 없습니다. 원하는 경우에도 마찬가지입니다.


답변

아래는 나를 위해 일한 것입니다-

QUOTE="'"
hive -e "alter table TBL_NAME set location $QUOTE$TBL_HDFS_DIR_PATH$QUOTE"


답변

편집 : (문제의 의견에 따라 🙂

나는 그때부터 이것을 조사해 왔습니다. 나는 레포가 누워있을 정도로 운이 좋았다. 여전히 명령을 작은 따옴표로 묶어야하는지 여부는 분명하지 않습니다. 나는 repo 구문을 조사했지만 당신이 필요하다고 생각하지 않습니다. 명령에 큰 따옴표를 사용한 다음 큰 따옴표를 이탈하면 필요한 작은 따옴표와 큰 따옴표를 사용할 수 있습니다.


답변

그냥 printf를 사용하십시오

대신에

repo forall -c '....$variable'

printf를 사용하여 변수 토큰을 확장 변수로 바꿉니다.

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

template='.... %s'

repo forall -c $(printf "${template}" "${variable}")


답변

변수는 작은 따옴표를 포함 할 수 있습니다.

myvar=\'....$variable\'

repo forall -c $myvar


답변

이것이 당신을 위해 작동합니까?

eval repo forall -c '....$variable'