如何从列表中删除元素?

如何从列表中删除元素?

我编写了一个输出主机名列表的命令,例如:

clab148node11
clab148node12
clab148node15
clab148node16

现在,我想删除那些不响应 ping 的节点。现在我有这样的东西:

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]or$node[space]或可以在所有情况下工作,具体取决于列表中[space]$node的位置(如果它位于中间,或者第一个或最后一个元素,则它之前和之后的空格将存在或不存在) 。它一次只能替换 1 个出现的情况,但您可以添加一个词尾来一次性删除所有出现的情况。$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

相关内容