문자열로 실행할 명령을 저장해야 하는 스크립트를 만들려고 합니다. 문제의 문자열에는 따옴표가 포함되어야 하며, 이를 실행하려고 할 때 bash는 추가 따옴표 문자를 추가하는데 이로 인해 어떤 경우에는 명령이 예상대로 실행되지 않습니다.
다음은 예제 스크립트입니다. 이 예제 스크립트에서 run 명령은 example
분명히 아무 작업도 수행하지 않으며 단순히 다음과 같이 말합니다 . 그러나 실행 중인 정확한 명령이 인쇄되도록 줄 에 command not found
추가했기 때문에 스크립트를 실행하고 내가 말하는 내용을 볼 수 있습니다. .-x
#!/bin/bash
예:
#!/bin/bash -x
#command typed explicitly
example -options "-i filename"
#command stored in string first
commandstring='example -options "-i filename"'
echo "running command: ${commandstring}"
${commandstring}
이 스크립트를 실행하면 다음과 같은 결과가 나옵니다(두 개의 "명령을 찾을 수 없음" 오류 무시).
+ example -options '-i filename'
+ commandstring='example -options "-i filename"'
+ echo 'running command: example -options "-i filename"'
running command: example -options "-i filename"
+ example -options '"-i' 'filename"'
따라서 명령줄 매개변수를 제공하여 첫 번째 줄이 예상대로 실행되는 것을 볼 수 있습니다.
-i filename
그러나 echo
명령이 완벽하게 실행되는 방식으로 문자열을 인쇄하더라도 문자열이 명령줄에 배치되면 문자열이 변경되고 전달되는 매개 변수는 다음과 같이 됩니다.
'"-i' '파일 이름"'
여기에는 추가 인용 문자가 포함되어 있으며 이로 인해 실제 스크립트에서 사용 중인 실제 명령이 실패하게 됩니다.
이를 방지할 수 있는 방법이 있나요?
답변1
를 사용하는 경우 bash
명령을 정확하게 저장하는 가장 쉬운 방법은 명령을 배열에 넣는 것입니다. 실행하려는 명령이 다음과 같은 경우:
example -options "-i filename"
다음을 사용하여 배열 변수에 저장할 수 있습니다.
commandline=(example -options "-i filename")
그런 다음 큰따옴표 안에 배열을 @ 확장하여 저장된 명령을 있는 그대로 정확하게 실행할 수 있습니다.
"${commandline[@]}"
여기서 알아야 할 중요한 점은 쉘이 "'\
명령줄에 직접 입력할 때 따옴표 문자( )를 에서처럼 변수 확장 내에서 찾을 때와 다르게 처리한다는 것입니다 ${commandstring}
. 명령줄에서 따옴표 문자에는 특별한 따옴표 기능이 있습니다. 매개변수 확장 내에서는 특수 문자가 아닌 일반 문자일 뿐입니다. 따라서 는 "-i filename"
명령줄에 입력하면 로 구문 분석되는 단일 단어이지만 변수의 동일한 문자는 및 -i filename
단어로 확장됩니다 ."-i
filename"
배쉬FAQ 50이 주제를 훨씬 더 자세히 다룹니다.