내가 스크립트를하고 있다고 가정 해보십시오.
some-command "$var1" "$var2" ...
그리고 var1
비어있는 경우 빈 문자열 대신 아무것도 대체하지 않으므로 실행 된 명령은 다음과 같습니다.
some-command "$var2" ...
그리고 아닙니다 :
some-command '' "$var2" ...
변수를 테스트하고 조건부로 포함시키는 것보다 간단한 방법이 있습니까?
if [ -n "$1" ]; then
some-command "$var1" "$var2" ...
# or some variant using arrays to build the command
# args+=("$var1")
else
some-command "$var2" ...
fi
bash, zsh 등에서 아무것도 확장 할 수없는 것보다 매개 변수 대체가 있습니까? 여전히 나머지 인수에서 globbing을 사용하고 싶을 수 있으므로 해당 변수를 비활성화하고 변수를 인용 해제하는 것은 옵션이 아닙니다.
답변
Posix 호환 쉘 및 Bash에는 ${parameter:+word}
다음 이 있습니다 .
경우 파라미터가 해제 또는 널, 널 치환한다; 그렇지 않으면 단어 의 확장 (또는 단어 가 생략 된 경우 빈 문자열 )이 대체됩니다.
그래서 당신은 할 수 있습니다 :
${var1:+"$var1"}
그리고 한 var1
확인하고, "$var1"
이 설정하고 비 비어있는 경우 (보통 이중 인용 규칙) 사용. 그렇지 않으면 아무것도 확장되지 않습니다. 전체 내용이 아니라 내부 부분 만 인용합니다.
zsh에서도 마찬가지입니다. 변수를 반복해야하므로 이상적이지는 않지만 원하는대로 정확하게 작동합니다.
빈 값으로 설정된 변수를 빈 인수로 확장하려면 ${var1+"$var1"}
대신 사용하십시오.
답변
그게 무슨 zsh
당신이 따옴표를 생략 할 때 기본적으로 수행합니다
some-command $var1 $var2
실제로 zsh에서 매개 변수 확장과 관련하여 여전히 따옴표가 필요한 유일한 이유는 매개 변수 확장을 인용하지 않을 때 다른 쉘에 영향을 미치는 다른 문제zsh
가 없기 때문에 해당 동작 (빈 제거)을 피하기위한 것입니다 (암시 적 분할 + 글로브) .
split과 glob를 비활성화하면 다른 POSIX와 같은 셸에서 동일한 작업을 수행 할 수 있습니다.
(IFS=; set -o noglob; some-command $var1 $var2)
이제 변수에 0 또는 1 값을 가질 수 있다면 스칼라 변수가 아닌 배열이어야하며 다음을 사용하십시오.
some-command "${var1[@]}" "${var2[@]}"
그리고 var1=(value)
when var1
은 하나의 값 var1=('')
을 포함하고, 하나의 빈 값 var1=()
을 포함하고 , 값 을 포함 하지 않을 때 사용합니다 .
답변
-n
드라이 런을 토글 하거나 토글 하지 않고 명령을 시작한 bash 스크립트에서 rsync를 사용 하여이 문제에 부딪 쳤습니다 . rsync 및 많은 gnu 명령 ''
은 유효한 첫 번째 인수로 사용되며 존재하지 않는 경우와 다르게 작동합니다.
널 (null) 매개 변수가 거의 완전히 보이지 않기 때문에 디버그하는 데 꽤 시간이 걸렸습니다.
rsync 목록의 누군가 가이 문제를 피하면서 코딩을 크게 단순화 하는 방법을 보여주었습니다 . 올바르게 이해하면 @ Stéphane Chazelas의 마지막 제안에 대한 변형입니다.
여러 개의 개별 변수로 명령 인수를 작성하십시오. 이들은 문제에 적합한 순서 나 논리로 설정할 수 있습니다.
그런 다음 마지막에 변수를 사용하여 모든 것을 올바른 위치에 배열로 구성하고 실제 명령의 인수로 사용하십시오.
이런 식으로 명령의 각 변형에 대해 반복되는 대신 코드의 한 위치에서만 명령이 실행됩니다.
비어있는 변수는이 방법을 사용하여 사라집니다.
나는 eval을 사용하는 것이 매우 싫은 것을 알고 있습니다. 모든 세부 사항을 기억하지는 못하지만, 공백을 포함하는 매개 변수를 처리하는 것과 관련이 있습니다.
예:
dry_run=''
if [[ it is a test run ]]
then
dry_run='-n'
fi
...
rsync_options=(
${dry_run}
-avushi
${delete}
${excludes}
--stats
--progress
)
...
eval rsync "${rsync_options[@]}" ...