여러 매개변수가 포함된 명령이 있습니다.
my_command --arg1 <arg1> \
--arg2 <arg2> \
--arg3 <arg3>
my_command
전달될 수도 있고 전달되지 않을 수도 있는 다양한 매개변수의 값을 설정하는 함수로 호출을 래핑합니다 .
run_my_command() {
if [[ ... ]]; then
ARG1FLAGS="--arg1 $ARG1"
else
ARG1FLAGS=''
fi
if [[ ... ]]; then
ARG2FLAGS="--arg2 $ARG2"
else
ARG2FLAGS=''
fi
if [[ ... ]]; then
ARG3FLAGS="--arg3 $ARG3"
else
ARG3FLAGS=''
fi
my_command $ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
}
어떤 경우에는 파일 이름 인수를 다음으로 전달해야 합니다 my_command
.
run_my_command() {
# ...
if [[ ... ]]; then
FILEARG="--input_file $SOME_FILE"
else
FILEARG=''
fi
my_command $FILEARG \
...
}
이 모든 것이 잘 작동합니다. 이제 조건부로 프로세스 대체를 사용하고 싶지만 FILEARG
당연히 작동하지 않습니다.
run_my_command() {
# ...
if [[ ... ]]; then
FILEFLAG='--input_file'
FILEARG=<(other_cmd)
else
FILEARG=''
fi
my_command $FILEFLAG $FILEARG \
...
}
런타임에 의해 my_command
익명 $FILEARG
파이프처럼 보이는 것이 /dev/fd/63
닫혔기 때문입니다.
이제 모든 것을 조건부로 넣어 my_command
이 문제를 해결했습니다 .
run_my_command() {
# Get ARG1, ARG2, ARG3...
if [[ ... ]]; then
my_command --input_file <(other_cmd) \
$ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
else
my_command $ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
fi
}
하지만 나는 반복을 좋아하지 않는다. 를 사용하여 뭔가를 할 수 있거나 다른 함수 eval
에 넣을 수 있을 것 같지만 my_command
아직 파악하지 못했습니다.my_command
전체 호출을 복제하지 않고 읽을 수 있는 파일을 생성하기 위해 조건부로 프로세스 대체를 사용하려면 어떻게 해야 합니까 my_command
?
나는 bash 4.4.19를 실행하고 있습니다. 놀랍게도 bash 3.2.57은 아래 Bash Hackers 위키에서 제안한 방식으로 작동하는 것 같습니다.
doit() {
local -r FOO=<(echo hi)
cat $FOO
}
doit
# bash 3.2.57:
$ ./test.sh
hi
# bash 4.4.19:
$ ./test.sh
cat: /dev/fd/63: Bad file descriptor
다음은 제가 확인한 몇 가지 질문이지만 다음으로부터 유효한 답변을 얻을 수 없습니다.
게다가,배쉬 해커 위키 노트오히려 신비롭게:
프로세스 대체가 함수에 대한 인수, 함수 호출 중 환경 변수 또는 함수 내의 할당으로 확장되면 프로세스 대체는 함수 내에서 또는 호출되는 모든 명령에서 사용할 수 있도록 "열린 상태로 유지"됩니다. 또는 이를 설정한 함수가 반환될 때까지. 호출 수신자에서 동일한 변수가 다시 설정되면 새 변수가 로컬이 아닌 한 이전 프로세스 대체가 해제되고 호출 수신자가 반환될 때 호출자가 변수를 사용할 수 없습니다.
기본적으로 함수 내 변수로 확장되는 프로세스 대체는 프로세스 대체가 발생하는 함수가 반환될 때까지 켜져 있습니다. 이는 함수 호출자가 설정한 지역 변수에 할당된 경우에도 마찬가지입니다. 동적 범위는 닫히는 것을 방지하지 않습니다.
그러나 함수의 변수에 프로세스 대체를 할당하는 것만으로는 "열린 상태를 유지할" 수 없습니다.
답변1
이는 질문을 하는 것과 비슷하지만 다른 매개변수를 단일 변수가 아닌 배열에 넣으면 중복이 줄어듭니다.$ARGnFLAGS
어떤 경우든, 이는 단어 분할이나 파일 이름 글로빙을 방해하지 않고 명령에 대한 인수를 얻을 수 있기 때문에 옳은 일이기도 합니다.
run_my_command() {
args=()
if [[ ... ]]; then
args+=(--arg1 "$ARG1")
fi
if [[ ... ]]; then
args+=(--arg2 "$ARG2")
fi
if [[ ... ]]; then
my_command --input_file <(other_cmd) "${args[@]}"
else
my_command "${args[@]}"
fi
}
답변2
run_my_command() {
# ...
if [[ ... ]]; then
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' RETURN
other_cmd >"$tmpfile"
FILEFLAG='--input_file'
FILEARG="$tmpfile"
else
FILEARG=''
fi
my_command $FILEFLAG $FILEARG \
...
return
}
...또는 그런 것.
즉, 프로세스 교체를 사용하는 대신 임시 파일을 사용하십시오.
답변3
다음 방법을 사용하여 eval
원하는 것을 얻을 수 있습니다.
run_my_command() {
# Get ARG1, ARG2, ARG3...
commandline="my_command $ARG1FLAGS $ARG2FLAGS $ARG3FLAGS"
if [[ ... ]]; then
commandline="$commandline --input_file <(other_cmd)"
fi
eval $commandline
}