Aqui está uma abordagem rápida e suja usando perl
:
$ perl -F, -lane '@l = grep {/srcip|srczone|protocol|dstip|dstzone|dstport|rule_name/} @F;
print join ",",@l' file
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All
O -a
faz o perl agir como o awk e dividir suas linhas de entrada no caractere dado por -F
, salvando-as como elementos da matriz @F
. Então, nós grep
da matriz e manteremos os elementos correspondentes às suas palavras de destino na matriz @l
e, finalmente, imprimiremos @l
unidos com vírgulas.
Observe que isso falhará se algum dos seus padrões puder ser subpadrão (digamos que você tenha foo=bar
e foobar=baz
).
Para listas mais longas de padrões de destino (supondo que você não queira escrever um script real), você pode armazená-los em uma matriz e juntá-los com |
para fazer o regex para grep. E adicionando \b
em torno de cada padrão que você protege dos subpadrões correspondentes. Se também removermos a matriz temporária desnecessária, obteremos:
$ perl -F, -lane '
BEGIN{
$pat="\b" . join "\b|",qw(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=)
} print join ",",grep {/$pat/}@F' file
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All
Our resident expert said it cannot be done in the bourne shell regardless of sed awk or [. . .. ] From your commant
Desculpe, mas isso é absurdo. Aqui está uma (muitas) maneiras de fazer isso em cada uma dessas ferramentas:
-
Bourne (novamente) shell. Não use isso, só mostro para demonstrar que é possível.
$ pat=(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=); $ o=""; while IFS=, read -a fields; do for f in "${fields[@]}"; do for pat in "${pat[@]}"; do [[ $f =~ $pat ]] && o="$f,$o" done done done < file ; echo ${o%,}
-
Awk
Salve seus padrões de destino em um arquivo:
$ cat patterns srcip srczone protocol dstip dstzone dstport rule_name
Então:
$ awk -F, '(NR==FNR){ pat[$0]++; next; } { for(i=1;i<=NF;i++){ split($i,a,"="); if(a[1] in pat){ printf "%s=%s,",a[1],a[2] } } print "" }' patterns file | sed 's/,$//' srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All
-
sed
(e shell)$ pat=(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=); $ for p in ${pat[@]}; do sed -E "s/.*($p[^,]*).*//" file; done | sed ':a;N;$!ba;s/\n/,/g' srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstzone=external,dstport=80,rule_name=Deny_All
-
Bourne shell (ou qualquer shell POSIX) + sed (como para 1., não faça isso, é possível, mas bobo)
$ set srcip= srczone= protocol= dstip= dstzone= dstport= rule_name= $ for f in "$@"; do sed "s/.*\($f[^,]*\).*//" file; done | sed ':a;N;$!ba;s/\n/,/g' srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstzone=external,dstport=80,rule_name=Deny_All