Home > OS >  Substituting stdout before writing to file
Substituting stdout before writing to file

Time:06-22

I am trying to substibute a variable from a stdout stream before writing it to file.

This is a tshark utility that is parsing some DNS stats and outputting to a file, it runs in the background

#tshark > $FILE 2>&1 &

The output looks something like this:

64.6.64.6 10.13.0.41 domain.com 3

What I am trying to do is substitute column 2 value with the regex output below:

grep 10.13.0.41 /etc/openvpn/openvpn-status.log |awk -F'[,:]' '{print $3}'

190.171.88.59

End result is $FILE will contain the line:

64.6.64.6 190.171.88.59 domain.com 3

CodePudding user response:

You can use sed for this job:

cat ./filter.sh
#!/bin/bash

while IFS='$\n' read -r line; do
    # Replace "echo 190.171.88.59" below with your commands to get the IP address
    NEW_IP=$(echo 190.171.88.59)
    printf "${line}\n" | sed "s/\ [0-9]\ \.[0-9]\ \.[0-9]\ \.[0-9]\ /\ ${NEW_IP}/"
done

$ cat tmp.txt 
64.6.64.6 10.13.0.41 domain.com 3
64.6.64.6 1.1.1.1 domain.com 3
64.6.64.6 2.2.2.2 domain.com 3
64.6.64.6 3.3.3.3 domain.com 3
64.6.64.6 4.4.4.4 domain.com 3
64.6.64.6 1.2.3.4 domain.com 3

$ cat tmp.txt | ./filter.sh 
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3

So in the end you'll have something like:

tshark | ./filter.sh > $FILE 2>&1 &

If the output takes time to show up in $FILE, you may have to check if tshark is buffering when printing to the pipe (see the -l parameter).

CodePudding user response:

Would you please try the following:

#!/bin/bash

ip=$(grep 10.13.0.41 /etc/openvpn/openvpn-status.log | awk -F'[,:]' '{print $3}')
tshark 2>&1 | awk -v ip="$ip" '{$2 = ip} 1' > "$FILE" &
  • ip=$( cmd ) assigns bash variable ip to the output of the command.
  • Awk option -v ip="$ip" sets the awk variable ip to the value of bash variable $ip then the second field is replaced with it.

CodePudding user response:

maybe make it a single through pipeline, plus one sub-shell ?

tshark 2>&1 | {m,g}awk '$(_ =_=_~_)=__' __="$( 
     
  {m,g}awk 'BEGIN { _*=(FS  = "^[^,:]*[,:][^,:]*[,:]|[,:]. $" (OFS = ORS = _))
       } _ { exit } _ = NF *= /[^0-9]?0?10[.]0?13[.]0 [.]0?41[^0-9]?/' \
                              \   
                         '/etc/openvpn/openvpn-status.log' )" > "$FILE" &

64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3
64.6.64.6 190.171.88.59 domain.com 3

CodePudding user response:

You already found that awk will do the job. You could simply pipe the output of tshark into awk,

(tshark 2>&1 | awk .... >$FILE) &
  • Related