![如何从列表中删除元素?](https://linux22.com/image/28612/%E5%A6%82%E4%BD%95%E4%BB%8E%E5%88%97%E8%A1%A8%E4%B8%AD%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0%EF%BC%9F.png)
我编写了一个输出主机名列表的命令,例如:
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