Leia cada linha - BASH

1

meu objetivo é armazenar cada linha foliada (na verdade, cada regra) em uma matriz. Minha saída:

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

Eu faço não quero limitar o número da regra. Cada cadeia tem várias regras.

Depois de executar meu código:

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

Quando eu faço eco de ${array[@]} , minha saída é um texto horrível em uma linha, então gostaria de separar cada linha. Na verdade, meu conteúdo dessa matriz consiste em um número irreal de regras de iptables (após echo ${!array[@]} )

Não sei como ter em condicional que as linhas foliadas sejam obrigatórias com separador definido (nova linha). Não tenho certeza se meu separador está certo.

Obrigado pela sua resposta M

    
por Michal N. 02.02.2016 / 10:41

1 resposta

1

Veja como eu faria isso. Primeiro, por simplicidade, vamos listar cada uma das cadeias individualmente, já que estou supondo que você queira saber a que cadeia uma regra pertence:

$ 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

Você pode obter uma lista de nomes de cadeias como este:

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

Agora, vamos usar alguns truques para simplesmente colocá-los em uma matriz:

# 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]'))'

Com o Bash 4, você também pode usar o mapfile builtin :

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

Agora, não sei seu caso de uso específico, mas se você consultar cada cadeia, uma por vez, também poderá remover os números de linha ou usá-los como chaves em uma matriz associativa, mas talvez eles está tudo bem sendo incluído.

Se você não quiser usar grep , mas ainda quiser excluir as duas primeiras linhas da matriz, poderá cancelar os primeiros dois elementos após o fato, assim:

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

Observe também que no seu exemplo original:

echo "${array[@]}"

colocará tudo em uma linha, seja em chaves de matriz separadas ou não. Uma maneira melhor de visualizar com precisão o array com um elemento por linha seria:

for rule in "${array[@]}"; do echo LINE: "$rule"; done
    
por 02.02.2016 / 11:05