각 루프 반복에서 명령 출력을 다른 변수에 할당하려면 어떻게 해야 합니까?

각 루프 반복에서 명령 출력을 다른 변수에 할당하려면 어떻게 해야 합니까?

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

for chain in http https ssh
do
 iptables -nvxL $chain | tail -1 | awk '{print $2}'
done

하지만 제가 정말로 원하는 것은 iptables각 반복에 대한 명령 출력을 다른 변수로 캡처하는 것입니다.이름현재 값과 같아야 합니다 chain.

따라서 첫 번째 루프 반복(여기서는 )의 경우 $chain다음 http과 같이 되기를 원합니다.

http=$(iptables -nvxL http | tail -1 | awk '{print $2}')

다음으로 나는 이것을 원합니다:

https=$(iptables -nvxL https | tail -1 | awk '{print $2}')

아이디어를 얻으셨기를 바라지만 어떻게 해야 할지 모르실 겁니다.

답변1

귀하의 경우에는 연관 배열을 사용합니다.

declare -A rules

for chain in http https ssh
do
   rules[$chain]=$(iptables -nvxL $chain | tail -1 | awk '{print $2}')
done

그런 다음 다음과 같이 출력을 역참조하여 출력에 액세스할 수 있습니다.

printf -- "%s\n" "${rules['http']}"

또는

for chain in http https ssh
do
    printf -- "%s\n" "${rules[$chain]}"
done

답변2

연관 배열에 대한 답은 거의 확실하게 여러분이 원하는 방식입니다.

그러나 , and ( http, 및 $references 사용 ) 라는 변수를 원하는 경우 이름이 포함된 변수에 명령 출력을 할당 할 수 있습니다 .httpsssh$http$httpssshprintf -v$chain

for chain in http https ssh; do
    printf -v "$chain" '%s' "$(iptables -nvxL "$chain" | tail -1 | awk '{print $2}')"
done

에 따르면 또한 참고하시기 바랍니다이 답변, 동일한 목적을 달성하기 위해 typeset다음을 사용할 수 있습니다 .declare

for chain in http https ssh; do
    typeset "$chain"="$(iptables -nvxL "$chain" | tail -1 | awk '{print $2}')"
done

eval이 답변을 하는 동안 피해를 입은 사람은 아무도 없습니다 . 또한 @penguin359의 답변처럼 루프에서 변수 값을 인쇄하려면 다음을 사용할 수 있습니다.bash 변수 간접변수 이름 역참조 - 다시 말하지만 evals는 필요하지 않습니다.

for chain in http https ssh; do
    echo ${!chain}
done

답변3

고쳐 쓰다:$2예제에 포함된 내용을 인용하는 것을 잊어버렸습니다 . 이제 OP가 요청한대로 작동합니다. 또한 이 답변의 요점과 사용법은 eval여러 구현에서 표준 Bourne 쉘 구문을 사용하여 이식 가능한 예제를 제공하는 것입니다. bash, dash 및 zsh에서 다음 코드를 모두 테스트했습니다. Dash는 Bourne 셸 구문과 더 제한적이고 일관성이 있는 구문을 사용하기 때문에 더 나은 이식성 테스트입니다. Debian/Ubuntu의 기본 쉘이기도 합니다 /bin/sh. Dash에는 합계가 없습니다 typeset. printf -v나는 그것이 추악하다고 생각 eval하지만 Bourne 쉘의 첫 번째 메커니즘이자 진정한 이식성을 달성하는 가장 좋은 방법입니다.

연관 배열이 좋은 방법이라고 생각하지만, Bash 외에 다른 Bourne 쉘에 정확하고 이식 가능한 그의 원래 질문에 대한 답변을 제공하고 싶었습니다. 동적 변수 이름은 전통적으로 다음과 같이 수행됩니다.

for chain in http https ssh; do
    eval $chain="\"\$(iptables -nvxL $chain | tail -1 | awk '{print \$2}')\""
done

Bourne 쉘의 연산자 eval는 변수를 명령으로 대체한 다음 완료되면 명령으로 다시 실행(재평가)하는 데 사용됩니다. 명령을 처음 대체한 후 $chain 변수와 첫 번째 참조 세트가 완료되어 다음과 같습니다.

http="$(iptables -nvxL http | tail -1 | awk '{print $2}')"

그런 다음 이는 명령 확장에 대한 변수 할당으로 평가됩니다 iptables. 내부 명령은 작은 따옴표를 사용하므로 명령문을 인용하는 데 사용할 수 없으므로 평가를 위해 및를 eval사용 "\"하고 \""결과 명령에 필요에 따라 큰 따옴표와 작은 따옴표를 전달합니다. 명령 확장 주위에 큰따옴표가 필요하지 않을 수도 있지만 명령이 여러 단어로 확장되면 일부 셸 문제가 발생합니다. 이것을 덤프하려면 다음과 같이 하십시오:

for chain in http https ssh; do
    eval echo \$$chain
done

첫 번째 달러 기호가 인용되어 전달됩니다. 결과적으로 루프 풀기 후에 다음 세 가지 명령이 실행됩니다.

echo $http
echo $https
echo $ssh

관련 정보