문자열로 실행할 명령을 저장해야 하는 스크립트를 만들려고 합니다. 문제의 문자열에는 따옴표가 포함되어야 하며, 이를 실행하려고 하면 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")
그런 다음 큰따옴표 안에 배열을 @expand하여 저장된 명령을 실행할 수 있습니다.
"${commandline[@]}"
여기서 알아야 할 중요한 점은 "'\
명령줄에 직접 입력할 때 쉘이 변수 확장에서와 동일한 방식으로 따옴표 문자()를 처리한다는 것입니다(예: ${commandstring}
명령줄에서 따옴표 문자에는 특별한 인용 기능이 있습니다. 특수 문자가 아닌 일반 문자인 매개변수 확장은 "-i filename"
명령줄에 입력할 때 단일 단어로 구문 분석되지만 변수의 동일한 문자는 및 -i filename
단어로 확장됩니다 ."-i
filename"
배쉬 FAQ 50이 주제는 더 자세히 다룹니다.