내가 아는 한, 쉘의 while 루프는 서브쉘에서 실행되므로 루프 외부의 변수를 수정할 수 없습니다.
쉘 스크립트를 작성 중인데 머신의 모든 내부 IP를 변수에 저장하고 싶기 때문에 for 루프를 사용하여 변수를 처리하고 iptables를 사용하여 하나씩 필터링합니다.
다음 코드를 작성할 수 있습니다.
ip route show default | awk '{ print $5 }' | while read line; do
ip address show dev ${line} scope global | awk '/inet / {sub(/\/.*/, "", $2); print $2}' | while read line; do
echo "${line} "
done
done
산출:
10.17.0.49
192.168.1.4
내 질문은 다음과 같습니다
while 루프에서 방출된 이러한 모든 행을 단일 변수에 어떻게 저장할 수 있습니까(while 루프 변수는 휘발성이므로)?
답변1
기본 경로에 포함된 인터페이스의 모든 전역 범위 로컬 주소를 인쇄하기 위해 보다 안정적인 방식으로 프로그래밍 방식으로 처리할 수 있는 JSON 형식을 사용하겠습니다.
perl -MJSON -le '
$default_routes = decode_json(qx(ip -j route show default));
for (@$default_routes) {$devs{$_->{dev}} = 1}
$addresses = decode_json(qx(ip -j address show));
for (@$addresses) {
if ($devs{$_->{ifname}}) {
for (@{$_->{addr_info}}) {
print $_->{local} if $_->{scope} eq "global";
}
}
}'
또는 동일한 것을 사용하십시오 jq
.
ip -j address show |
jq -r --argjson devs "$(
ip -j route show default|jq 'map({"key":.dev})|from_entries'
)" '.[]|select(.ifname|in($devs)).addr_info[]|
select(.scope == "global").local'
(JSON 출력을 지원하려면 비교적 새로운 버전이 필요합니다 iproute2
).
이 항목(또는 더 일반적으로 명령의 출력 각 줄)을 array 에 넣으려면 다음을 bash
사용하세요.
readarray -t array < <(
that-command above
)
목표가 기본 경로를 통해 전송된 패킷이 얻을 수 있는 소스 IP 주소를 얻는 것이라면 예제를 참조하세요.내 대답도착하다내 IP 주소를 어떻게 얻고 이를 쉘 스크립트의 변수에 저장합니까?.
답변2
실제 질문에 간결하게 대답하려면 어쨌든 while 루프의 출력 컨텍스트를 저장하십시오.
출력을 파일에 저장합니다 /path/to/file
. 예를 들면 다음과 같습니다.
while command; do
thing
done > /path/to/file
출력을 변수에 저장합니다 my_var
. 예를 들면 다음과 같습니다.
my_var="$(while command; do thing; done)"
답변3
나는 이를 수행하는 두 가지 방법을 알고 있습니다(배쉬에서):
- 프로세스 대체라는 것을 사용하십시오
< <(command)
(이것은 내용을 루프로 파이프하지 않습니다while
). - 호출된 명령을 사용하여 그룹화합니다
{ code or commands }
.
따라서 모든 IP를 변수(또는 이 경우 배열)에 저장하려면 다음 코드를 사용할 수 있습니다.
프로세스 대안:
process_subs () {
local array=()
while read -r line; do
while read -r line; do
array+=("$line")
done < <(ip address show dev "${line}" scope global | awk '/inet / {sub(/\/.*/, "", $2); print $2}')
done < <(ip route show default | awk '{ print $5 }')
echo Array: "${array[@]}"
echo Length: ${#array[@]}
}
명령 그룹화:
command_grouping () {
ip route show default | awk '{ print $5 }' | while read -r line; do
ip address show dev "${line}" scope global | awk '/inet / {sub(/\/.*/, "", $2); print $2}' | {
local array=()
while read -r line; do
array+=("$line")
done
echo Array: "${array[@]}"
echo Length: ${#array[@]}
}
done
}