[linux] 쉘 스크립트의 변수에 명령을 저장하는 방법은 무엇입니까?

나중에 사용할 명령을 변수에 저장하고 싶습니다 (명령의 출력이 아니라 명령 자체).

다음과 같은 간단한 스크립트가 있습니다.

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.