나중에 사용할 명령을 변수에 저장하고 싶습니다 (명령의 출력이 아니라 명령 자체).
다음과 같은 간단한 스크립트가 있습니다.
command="ls";
echo "Command: $command"; #Output is: Command: ls
b=`$command`;
echo $b; #Output is: public_html REV test... (command worked successfully)
그러나 조금 더 복잡한 것을 시도하면 실패합니다. 예를 들어
command="ls | grep -c '^'";
출력은 다음과 같습니다.
Command: ls | grep -c '^'
ls: cannot access |: No such file or directory
ls: cannot access grep: No such file or directory
ls: cannot access '^': No such file or directory
나중에 사용할 수 있도록 이러한 명령 (파이프 / 다중 명령 포함)을 변수에 저장하는 방법에 대한 아이디어가 있습니까?
답변
eval 사용 :
x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"
답변
마십시오 하지 사용 eval
! 임의의 코드가 실행될 위험이 있습니다.
BashFAQ-50- 변수에 명령을 넣으려고하는데 복잡한 경우는 항상 실패합니다.
배열에 넣고 큰 따옴표 "${arr[@]}"
로 모든 단어를 확장 하여 단어 분할 로 인해 단어 가 분할 되지 않도록합니다 .IFS
cmdArgs=()
cmdArgs=('date' '+%H:%M:%S')
내부 배열의 내용을 확인하십시오. 을 declare -p
사용하면 각 명령 매개 변수를 사용하여 별도의 인덱스로 배열의 내용을 볼 수 있습니다. 그러한 인수 중 하나에 공백이 포함 된 경우 배열에 추가하는 동안 내부를 인용하면 Word-Splitting으로 인해 분할되지 않습니다.
declare -p cmdArgs
declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")'
다음과 같이 명령을 실행하십시오.
"${cmdArgs[@]}"
23:15:18
(또는) 모두 bash
함수를 사용 하여 명령을 실행합니다.
cmd() {
date '+%H:%M:%S'
}
다음과 같이 함수를 호출하십시오.
cmd
POSIX sh
에는 배열이 없으므로 가장 가까운 방법은 위치 매개 변수에 요소 목록을 작성하는 것입니다. 다음 sh
은 메일 프로그램을 실행 하는 POSIX 방법입니다.
# POSIX sh
# Usage: sendto subject address [address ...]
sendto() {
subject=$1
shift
first=1
for addr; do
if [ "$first" = 1 ]; then set --; first=0; fi
set -- "$@" --recipient="$addr"
done
if [ "$first" = 1 ]; then
echo "usage: sendto subject address [address ...]"
return 1
fi
MailTool --subject="$subject" "$@"
}
이 접근 방식은 리디렉션없이 간단한 명령 만 처리 할 수 있습니다. 리디렉션, 파이프 라인, for / while 루프, if 문 등을 처리 할 수 없습니다.
또 다른 일반적인 사용 사례는 curl
여러 헤더 필드 및 페이로드로 실행할 때 입니다. 항상 아래와 같이 인수를 정의 curl
하고 확장 된 배열 콘텐츠를 호출 할 수 있습니다.
curlArgs=('-H' "keyheader: value" '-H' "2ndkeyheader: 2ndvalue")
curl "${curlArgs[@]}"
다른 예시,
payload='{}'
hostURL='http://google.com'
authToken='someToken'
authHeader='Authorization:Bearer "'"$authToken"'"'
이제 변수가 정의되었으므로 배열을 사용하여 명령 인수를 저장하십시오.
curlCMD=(-X POST "$hostURL" --data "$payload" -H "Content-Type:application/json" -H "$authHeader")
이제 적절한 인용 확장을 수행하십시오.
curl "${curlCMD[@]}"
답변
var=$(echo "asdf")
echo $var
# => asdf
이 방법을 사용하면 명령이 즉시 평가되고 반환 값이 저장됩니다.
stored_date=$(date)
echo $stored_date
# => Thu Jan 15 10:57:16 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 10:57:16 EST 2015
백틱과 동일
stored_date=`date`
echo $stored_date
# => Thu Jan 15 11:02:19 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 11:02:19 EST 2015
에서 eval을 사용하면 $(...)
나중에 평가되지 않습니다.
stored_date=$(eval "date")
echo $stored_date
# => Thu Jan 15 11:05:30 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 11:05:30 EST 2015
eval을 사용하면 사용시 평가 eval
됩니다.
stored_date="date" # < storing the command itself
echo $(eval "$stored_date")
# => Thu Jan 15 11:07:05 EST 2015
# (wait a few seconds)
echo $(eval "$stored_date")
# => Thu Jan 15 11:07:16 EST 2015
# ^^ Time changed
위의 예에서 인수가있는 명령을 실행해야하는 경우 저장중인 문자열에 입력하십시오.
stored_date="date -u"
# ...
bash 스크립트의 경우 이는 거의 관련이 없지만 마지막 참고 사항입니다. 조심하세요 eval
. 사용자가 제어하는 문자열 만 평가하고 신뢰할 수없는 사용자로부터 온 문자열이나 신뢰할 수없는 사용자 입력에서 빌드 된 문자열은 절대로 평가하지 마십시오.
- 명령을 인용하도록 상기시켜 준 @CharlesDuffy에게 감사드립니다!
답변
bash의 경우 다음과 같이 명령을 저장하십시오.
command="ls | grep -c '^'"
다음과 같이 명령을 실행하십시오.
echo $command | bash
답변
다양한 방법을 시도했습니다.
printexec() {
printf -- "\033[1;37m$\033[0m"
printf -- " %q" "$@"
printf -- "\n"
eval -- "$@"
eval -- "$*"
"$@"
"$*"
}
산출:
$ printexec echo -e "foo\n" bar
$ echo -e foo\\n bar
foon bar
foon bar
foo
bar
bash: echo -e foo\n bar: command not found
보시다시피 세 번째 만 "$@"
올바른 결과를 제공했습니다.
답변
다음 주소로 주문을 등록하십시오. X=$(Command)
이것은 호출되기 전에도 여전히 실행됩니다. 이를 확인하고 확인하려면 다음을 수행하십시오.
echo test;
X=$(for ((c=0; c<=5; c++)); do
sleep 2;
done);
echo note the 5 seconds elapsed
답변
#!/bin/bash
#Note: this script works only when u use Bash. So, don't remove the first line.
TUNECOUNT=$(ifconfig |grep -c -o tune0) #Some command with "Grep".
echo $TUNECOUNT #This will return 0
#if you don't have tune0 interface.
#Or count of installed tune0 interfaces.