나는 이런 일을 하고 싶다.
$ touch a\ b
$ cmd=cat\ a\ b
$ echo $cmd
cat a b
$cmd
cat: a: No such file or directory
cat: b: No such file or directory
파일에 공백에 문제가 있습니다 a b
. 그래서 이것을 시도했습니다.
$ cmd=cat\ a\\\ b
$ echo $cmd
cat a\ b
$ $cmd
cat: a\': No such file or directory
cat: b: No such file or directory
이것도 실패했습니다. $cmd
고양이가 뛰지 못하게 하려면 어떻게 해야 하나요 a b
?
답변1
set -- cat "a b"
"$@"
이것은 cat
단일 인수로 실행됩니다 a b
. 확장 "$@"
(큰따옴표 포함!)은 개별적으로 인용된 위치 매개변수 목록이 됩니다. 위치 매개변수는 를 통해 설정됩니다 set
.
그러나 명령 이름이 목록 자체에 포함되는 경우는 드뭅니다. 더 흔해질 것이다
set -- "a b"
cat "$@"
또는 실제 명령 이름 변수를 유지하려면
cmd=cat
set -- "a b"
"$cmd" "$@"
파일 이름 피연산자를 설정하고 명령을 실행하는 사이에 명령에 더 많은 파일 이름이나 옵션을 추가하려면 다음을 수정하세요 $@
.
cmd=cat
set -- "a b"
# later (adding more files to the end):
set -- "$@" "more files" "some glob here-"[0-9]
# later (adding an option at the front):
set -- -v "$@"
"$cmd" "$@"
$@
명령 이름이 이미 존재하는 경우 앞에 명령 이름을 추가하는 것은 어렵습니다. 이런 경우에는 shift
임시로 명령어 이름을 $@
별도의 변수에 넣어두고 추가하고 싶은 내용을 추가한 후 명령어 이름을 다시 추가해야 합니다.
cmd=$1
shift
set -- "$cmd" -v "$@"
우리는 일반적으로 위치 매개변수를 설정하는 set --
것보다 사용하기를 원합니다 . 명령줄 인수 목록에서 이 지점 이후의 명령줄 옵션을 검색하는 명령줄 옵션 구문 분석기를 set
중지합니다 . --
가 없으면 완전히 다른 경우처럼 문자열 앞에 with 를 추가하는 --
것은 불가능합니다 .-v
$@
set
set -v
관련된:
답변2
따옴표를 사용하거나 사용 echo $cmd
하지 $cmd
않으면 콘텐츠에서 분할+글로브가 호출됩니다 $cmd
. 이는 echo cat a b
셸의 구문 해석을 사용하여 에 전달된 별도의 인수로 cat
분리 a
할 때 발생하는 상황과는 아무런 관련이 없습니다 .b
echo
Split+glob의 분할 부분은 SPC의 기본 포함을 기반으로 하므로 $IFS
분할 단어에는 SPC가 포함되지 않습니다. 다른 구분 기호를 사용해야 합니다.
IFS=: # split on :
set -o noglob # disable glob part
cmd='cat:a b'
printf '<%s>\n' $cmd # split+glob
$cmd # split+glob
cmd
eval
또는 분할+glob에 의존하는 대신 셸 명령줄(셸 언어의 코드)을 포함하고 호출하여 해당 코드를 해석할 수 있습니다.
cmd='cat "a b"'
eval "$cmd" # note the quotes to disable split+glob