读取每一行 - BASH

读取每一行 - BASH

我的目标是将每条分叶线(实际上是每条规则)存储到一个数组中。我的输出:

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     udp  --  109.224.241.0/24     0.0.0.0/0            udp dpt:5060
2    ACCEPT     udp  --  109.224.241.0/24     0.0.0.0/0            udp dpt:4569
3    ACCEPT     udp  --  217.14.138.0/24      0.0.0.0/0            udp dpt:5060
4    ACCEPT     udp  --  217.14.138.0/24      0.0.0.0/0            udp dpt:4569
5    ACCEPT     udp  --  172.30.33.0/24       0.0.0.0/0            udp dpt:5060
6    ACCEPT     udp  --  172.30.33.0/24       0.0.0.0/0            udp dpt:4569
7    ACCEPT     udp  --  212.11.91.0/24       0.0.0.0/0            udp dpt:5060
8    ACCEPT     udp  --  212.11.91.0/24       0.0.0.0/0            udp dpt:4569
9    ACCEPT     udp  --  212.11.64.0/19       0.0.0.0/0            udp dpt:5060
10   ACCEPT     udp  --  212.11.64.0/19       0.0.0.0/0            udp dpt:4569
11   ACCEPT     udp  --  77.240.48.0/20       0.0.0.0/0            udp dpt:5060
12   ACCEPT     udp  --  77.240.48.0/20       0.0.0.0/0            udp dpt:4569
13   LOG        udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:4569 LOG flags 0 level 4 prefix "AsteriskHack:"
14   DROP       udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:4569
15   LOG        udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:5060 LOG flags 0 level 4 prefix "AsteriskHack:"
16   DROP       udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:5060

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

我愿意不是想要限制规则数量。每个链都有几条规则。

我执行代码后:

while IFS='' read line -r || [[ -n "$line" ]]; do
     array+=($line)
done < <(iptables -L --line-numbers)

当我回显时,${array[@]}我的输出是一行可怕的文本,所以我想分隔每一行。实际上我的这个数组的内容由不真实数量的 iptables 规则组成(在 echo 之后${!array[@]}

我不知道如何在条件下使叶状行必须具有定义的分隔符(新行)。我不确定我的分隔符是否正确。

谢谢你的回复,M

答案1

我就是这样做的。首先,为了简单起见,让我们单独列出每个链,因为我假设您想知道规则属于哪个链:

$ iptables -L INPUT --line-numbers

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     udp  --  109.224.241.0/24     0.0.0.0/0            udp dpt:5060
2    ACCEPT     udp  --  109.224.241.0/24     0.0.0.0/0            udp dpt:4569
3    ACCEPT     udp  --  217.14.138.0/24      0.0.0.0/0            udp dpt:5060
4    ACCEPT     udp  --  217.14.138.0/24      0.0.0.0/0            udp dpt:4569
5    ACCEPT     udp  --  172.30.33.0/24       0.0.0.0/0            udp dpt:5060
6    ACCEPT     udp  --  172.30.33.0/24       0.0.0.0/0            udp dpt:4569
7    ACCEPT     udp  --  212.11.91.0/24       0.0.0.0/0            udp dpt:5060
8    ACCEPT     udp  --  212.11.91.0/24       0.0.0.0/0            udp dpt:4569
9    ACCEPT     udp  --  212.11.64.0/19       0.0.0.0/0            udp dpt:5060
10   ACCEPT     udp  --  212.11.64.0/19       0.0.0.0/0            udp dpt:4569
11   ACCEPT     udp  --  77.240.48.0/20       0.0.0.0/0            udp dpt:5060
12   ACCEPT     udp  --  77.240.48.0/20       0.0.0.0/0            udp dpt:4569
13   LOG        udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:4569 LOG flags 0 level 4 prefix "AsteriskHack:"
14   DROP       udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:4569
15   LOG        udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:5060 LOG flags 0 level 4 prefix "AsteriskHack:"
16   DROP       udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:5060

您可以获得这样的链名称列表:

CHAINS="$(iptables -L | awk '/Chain /{print $2}')"

现在,让我们使用一些技巧来简单地将它们放入数组中:

# We can just define the array from the contents of our command
# output, using \r or \n as a field separator.
# We use grep to ignore lines that don't start with a number.
IFS=$'\r\n' GLOBIGNORE='*' command eval 'INPUT_RULES=($(iptables -L INPUT --line-numbers | grep '^[0-9]'))'

对于 Bash 4,您还可以使用mapfile内置:

IFS=$'\r\n' mapfile INPUT_RULES < <(iptables -L INPUT --line-numbers | grep '^[0-9]')

现在,我不知道您的具体用例,但是如果您一次查询每个链,您还应该能够删除行号或将它们用作关联数组中的键,但也许它们很好包括。

如果您不想使用grep,但仍想从数组中排除前两行,则可以在事后取消设置前两个元素,如下所示:

array=("${array[@]:2}")

另请注意,在您原来的示例中:

echo "${array[@]}"

会将所有内容放在一行上,无论它是否在单独的数组键中。准确查看每行一个元素的数组的更好方法是:

for rule in "${array[@]}"; do echo LINE: "$rule"; done

相关内容