대시로 된 이스케이프 공백

대시로 된 이스케이프 공백

나는 이런 일을 하고 싶다.

$ 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$@setset -v

관련된:

답변2

따옴표를 사용하거나 사용 echo $cmd하지 $cmd않으면 콘텐츠에서 분할+글로브가 호출됩니다 $cmd. 이는 echo cat a b셸의 구문 해석을 사용하여 에 전달된 별도의 인수로 cat분리 a할 때 발생하는 상황과는 아무런 관련이 없습니다 .becho

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

cmdeval또는 분할+glob에 의존하는 대신 셸 명령줄(셸 언어의 코드)을 포함하고 호출하여 해당 코드를 해석할 수 있습니다.

cmd='cat "a b"'
eval "$cmd" # note the quotes to disable split+glob

관련 정보