リストから要素を削除する方法は?

リストから要素を削除する方法は?

ホスト名リストを出力するコマンドを作成しました。たとえば、次のようになります。

clab148node11
clab148node12
clab148node15
clab148node16

ここで、pingに応答しないノードを削除したいと思います。今、次のようなものがあります。

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

$result今、ゼロ以外のノードをどのように削除しますか?

答え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

関連情報