Here's a quick'n dirty approach using 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
The -a
makes perl act like awk and split its input lines on the character given by -F
, saving them as elements of the array @F
. Then, we grep
the array and keep elements matching your target words in the array @l
, and finally print @l
joined with commas.
Note that this will fail if any of your patterns can be subpatterns (say you have foo=bar
and foobar=baz
).
For longer lists of target patterns (assuming you don't want to write an actual script), you could store them in an array and join them with |
to make the regex for grep. And by adding \b
around each pattern you protect from matching subpatterns as well. If we also remove the needless temp array, we get:
$ 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
Sorry, but that's patently absurd. Here's one (of many) ways of doing it in each of those tools:
Bourne (again) shell. Don't use this, I only show it to demonstrate it is possible.
$ 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
Save your target patterns in a file:
$ cat patterns
srcip
srczone
protocol
dstip
dstzone
dstport
rule_name
Then:
$ 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
(and shell)
$ pat=(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=);
$ for p in ${pat[@]}; do
sed -E "s/.*($p[^,]*).*/\1/" 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 (or any POSIX shell) + sed (as for 1., don't do this, it's possible but silly)
$ set srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=
$ for f in "$@"; do sed "s/.*\($f[^,]*\).*/\1/" 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