다음과 같은 답변이것패스 제어 방법을 잘 설명해줍니다.모두명령을 통해 변수.
인수별로 이 작업을 수행하는 방법을 알아보고 싶었습니다. 관찰하십시오(이것은 에서 테스트되었습니다 zsh
).
$ program() { echo 1: $1 2: $2 3: $3; }
$ run() { program "$@"; }
$ run2() { echo `run $1`; }
$ run2 'a b' c
1: a b 2: 3:
공백이 포함된 문자열인 첫 번째 인수를 전달하고 해당 $@
스타일을 다른 명령에 연결하는 방법을 원합니다. 예를 들어 run2 "a b" c
생산해야 한다1: a 2: b 3:
이 시점에서 나는 당면한 문제를 해결했습니다. 왜냐하면 테스트 코드가 zsh에서 테스트할 때 중단되더라도 일단 실제 bash 스크립트로 구현되면 작동하기 때문입니다.
이는 "안전"하지 않은 문자열 및 인수 처리의 일부 복잡성에 의존할 수 있음을 나타냅니다. 따라서 이는 이 동작을 안정적으로 달성하기 위한 보다 강력한 방법에 대한 의견을 요청하는 것입니다.
답변1
run2
여기서 중요한 bash와 zsh의 차이점은 호출 방식 run
, 특히 인용되지 않은 상태로 두는 효과에 있습니다 $1
.
- zsh에서는
run $1
"비어 있으면 제거" 연산자를 에 적용합니다 . 즉 , 에 전달된 첫 번째 인수로$1
호출합니다 . 단, 의 첫 번째 인수가 비어 있는 경우(또는 인수 없이 호출된 경우) 는 없이 호출됩니다. 논쟁.run
run2
run2
run2
run
- Bash와 같은 다른 Bourne 스타일 셸에서는
run $1
"split+glob" 연산자를 에 적용합니다$1
. 즉, 첫 번째 인수를run2
공백으로 구분된 청크로 분할하고, 각 조각을 와일드카드 패턴²으로 해석하고, 하나 또는 일치하는 각 와일드카드 패턴을 대체합니다. 일치 목록으로 더 많은 파일을 생성합니다.
따라서 zsh(인수는 변경되지 않은 상태로 전달됨)에서 인수를 사용하여 run2 'a b' c
호출 하지만 두 인수 와 bash(공백으로 구분된 조각으로 분할)를 사용하여 호출합니다.run
a b
run
a
b
공백이 포함된 문자열인 첫 번째 인수를 전달하고 해당
$@
스타일을 다른 명령에 연결하는 방법을 원합니다. 예를 들어run2 "a b" c
생산해야 한다1: a 2: b 3:
귀하의 설명과 귀하의 예는 서로 다른 것을 말합니다. 첫 번째 인수를 다른 명령에 전달하려면 를 사용하여 run "$1"
인수가 분할되지 않았는지 확인하세요. 인수를 변경하지 않고 전달하는 것이 "$@"
.
실제로 원하는 것은 첫 번째 인수를 run2
공백으로 구분된 덩어리로 나누는 것 같습니다. Bash에서는 와일드카드 확장을 끈 다음 ( IFS
기본값에서 변경되지 않는다고 가정하고) 인용되지 않은 확장을 사용하여 이를 수행할 수 있습니다.
run2 () ( set -f; run $1; )
( echo "$(somecommand)"
기본적으로 서브셸에서 실행하는 것과 동일하며 명령 출력에 분할+glob을 적용하는 것이 somecommand
아니라 이것이 의미하는 것으로 보이므로 중복된 echo-command-substitution을 제거했습니다.)echo $(somecommand)
zsh에서는 =
매개변수 대체 문자를 사용하여 값에 대해 월드 분할(글로빙 없음)을 수행할 수 있습니다.
run2 () { run $=1; }
zsh의 구문은 일반 sh의 구문과 호환되지 않습니다. zsh에서 sh 스크립트를 소스로 사용하려면 emulate
다음 건물을 사용할 수 있습니다.
emulate sh -c '. myscript.sh'
emulate ksh
ksh의 일부 기능을 에뮬레이트하는 데 사용됩니다 . 이것은 모든 bash 기능을 에뮬레이션하지는 않지만 배열을 사용할 수 있도록 해줍니다.
¹ 보다 일반적으로는 의 값을 기준으로 합니다 IFS
.
² 로 이 기능을 끄지 않은 경우 set -f
.
답변2
인용과 놀라움의 세계에 오신 것을 환영합니다.
주요 문제는 zsh
기본적으로 IFS 문자로 분할되지 않는다는 것입니다.
즉, 다른 모든 껍질과 다릅니다.
인용이 쉘 작동 방식을 어떻게 변경하는지 테스트하려면 인용된 버전과 인용되지 않은 코드 버전을 모두 테스트하는 코드가 필요합니다.
귀하의 코드(몇 가지 변수 추가):
program() { printf '%02d-1: %6s 2: %6s 3: %6s' "$i" "$1" "$2" "$3"; }
runa() { program "$@" ; }
run1() { echo "`runa $1 $2 $3 `"; }
run1 'a b' c
세부 사항을 확장해 보겠습니다.
sh
거주지 를 가리키는 로컬 링크를 생성한다고 가정해 보겠습니다 zsh
.
ln -s "/usr/bin/zsh" ./sh
그리고, 다음 스크립트를 파일에 복사한다고 가정해 보겠습니다 so
.
인용된 변수와 인용되지 않은 변수를 사용하여 각 함수를 반복하는 스크립트:
program() { printf '%02d-1: %6s 2: %6s 3: %6s' "$i" "$1" "$2" "$3"; }
runa() { program "$@"; }
runb() { program $@ ; }
run1() { echo "`runa "$1" "$2" "$3"`"; }
run2() { echo "`runb "$1" "$2" "$3"`"; }
run3() { echo "`runa $1 $2 $3`"; }
run4() { echo "`runb $1 $2 $3`"; }
for i in `seq 4`; do
run"$i" 'a b' c
done
그런 다음 실행 시 다음이 인쇄됩니다.
# Any shell (except zsh) results.
01-1: a b 2: c 3:
02-1: a 2: b 3: c
03-1: a 2: b 3: c
04-1: a 2: b 3: c
모두 인용된 첫 번째 실행(run1)만 계속 'a b'
조인됩니다.
그러나 zsh는 모든 내용이 항상 인용된 것처럼 작동합니다.
# ZSH results.
01-1: a b 2: c 3:
02-1: a b 2: c 3:
03-1: a b 2: c 3:
04-1: a b 2: c 3:
zsh를 에뮬레이션 중입니다.
또는 zsh
로 호출되면 이전 쉘을 에뮬레이션할 것으로 예상됩니다 . 그러나 실제로 이것은 항상 사실이 아닙니다.sh
ksh
$ ./sh ./so # emulated sh
01-1: a b 2: c 3:
02-1: a b 2: c 3:
03-1: a 2: b 3: c
04-1: a 2: b 3: c
두 번째 줄은 다른 쉘의 두 번째 줄과 다릅니다.
다음을 수행하는 것이 좋습니다.이 질문에 대한 답을 읽어보세요