목록에서 요소를 제거하는 방법은 무엇입니까?

목록에서 요소를 제거하는 방법은 무엇입니까?

호스트 이름 목록을 출력하는 명령을 작성했습니다. 예를 들면 다음과 같습니다.

clab148node11
clab148node12
clab148node15
clab148node16

이제 핑에 응답하지 않는 노드를 제거하고 싶습니다. 이제 다음과 같은 것이 있습니다.

for node in $nodes
do
         result=$(ping -c 1 $node; echo $?)
done

$result이제 0이 아닌 노드를 어떻게 삭제하나요 ?

답변1

나는 새 목록을 만들고 이전 목록을 새 목록으로 바꾸는 것을 선호합니다.

nodes="127.0.0.1 1.2.3.4 1.2.3.4 "
nodes_out=
for node in $nodes
do 
    ping -c 1 $node >/dev/null 2>&1 && nodes_out+=$node
done
nodes=$nodes_out

답변2

@manatwork가 말했듯이 유효한 노드를 사용하여 새 목록을 작성하는 것이 더 간단하고 안전해 보입니다.

그러나 "$nodes"는 for 루프의 첫 번째 반복 전에 평가되므로 동일한 루프 중에 이를 변경할 수 있습니다.

$ nodes="127.0.0.1 1.2.3.4 1.2.3.4 "
$ for node in $nodes; do
      result=$(ping -c 1 $node >/dev/null 2>/dev/null; echo $?);
      if [ "$result" -ne 0 ]; 
      then    nodes=$(echo $nodes | sed -e "s/ *$node */ /"); 
      fi;
      echo result=$result node=$node nodes=$nodes ;    
  done ;

참고: 내 sed는 목록의 위치 에 따라 모든 경우에 교체하거나 작동합니다 [space]$node[space]( 중간, 첫 번째 또는 마지막 요소에 있는 경우 앞뒤 공백이 있거나 없음). 한 번에 1개의 항목만 바꿀 수 있지만 접미사를 추가하여 모든 항목을 한 번에 제거할 수 있습니다.$node[space][space]$node$node$nodes/g

이 출력은 다음과 같습니다.

result=0 node=127.0.0.1 nodes=127.0.0.1 1.2.3.4 1.2.3.4
result=1 node=1.2.3.4 nodes=127.0.0.1 1.2.3.4
result=1 node=1.2.3.4 nodes=127.0.0.1

답변3

또 다른 옵션은 단순히 역방향 grep을 사용하여 목록에서 일치하는 모든 항목을 찾는 것입니다.아니요일치하는 호스트:

for node in $nodes
do
    if ! `ping -c 1 $node > /dev/null 2>&1`; then 
        nodes="`echo \"$nodes\" | grep -v \"$node\"`"
    fi
done

관련 정보