1

I have this perfectly working command:

netstat -tuplean | awk '{NR>1; if( $6 ~ /ESTABLISHED/ ) print "\033[0;31m" $5 " \033[01;31m"$6;if ($6 ~ /_WAIT/ ) print "\033[0;34m"$5 " \033[01;32m"$6}' 

I cannot wrap it into a watch command. Here is what I tried:

  1. escape all single quotes (')

    watch 'netstat -tuplean | awk '\''{NR>1; if( $6 ~ /ESTABLISHED/ ) print "\033[0;31m" $5 " \033[01;31m"$6 if ($6 ~ /_WAIT/ ) print "\033[0;34m"$5 " \033[01;32m"$6}'\''' 

    output:

    ^[0;31m34.210.39.83:443 ^[01;31mESTABLISHED ^[0;31m34.107.221.82:80 ^[01;31mESTABLISHED ^[0;31m34.107.221.82:80 ^[01;31mESTABLISHED ^[0;34m34.117.59.81:80 ^[01;32mTIME_WAIT ^[0;34m34.117.59.81:80 ^[01;32mTIME_WAIT ^[0;31m192.168.0.1:67 ^[01;31mESTABLISHED 
  2. escape both single and double quotes (' and ")

    watch 'netstat -tuplean | awk '\''{NR>1; if( $6 ~ /ESTABLISHED/ ) print '\'"\033[0;31m'\'" $5 " \033[01;31m'\'"$6 if ($6 ~ /_WAIT/ ) print '\'"\033[0;34m'\'"$5 '\'" \033[01;32m'\'"$6}'\''' 

    output:

     bash: syntax error near unexpected token `print' 
  3. export the command and then call it back this way:

     while : do ...<cmd>...; sleep 2;done watch -n 3 -x bash -c "$cmd" 

    it does not work neither because the same problem occurs when defining the variable.

  4. I tried to make a script using while : do ...<cmd>...; sleep 2;done

    it does not work because it looks like the sleep delay is not taken into account; as a result, the output comes out too fast -- there is no way to read something.

2 Answers 2

4

You did not share the complete code you used in your loop-based attempts, so here are a few options you have to avoid handling multiple levels of quoting, freely based on a slightly modified AWK script.

You may save your code as an executable file:

#!/bin/bash netstat -tuplean | awk ' $6 ~ /ESTABLISHED/ { print "\033[0;31m" $5 " \033[01;31m"$6 } $6 ~ /_WAIT/ { print "\033[0;34m"$5 " \033[01;32m"$6 } $6 ~ /TIME_WAIT/ { print "\033[0;34m"$5 " \033[01;32m"$6 } END { printf("%s","\033(B\033[m") } # Turn fancy formatting off' 

and make watch run it, noting that, as pointed out in the answer you already have, you also need the --color option:

watch -n 3 --color ./my_script 

Alternatively, you may use an infinite loop — I am unable to guess why, in your case, "the sleep delay is not taken into account"; this seems to work as expected:

while : do clear netstat -tuplean | awk ' $6 ~ /ESTABLISHED/ { print "\033[0;31m" $5 " \033[01;31m"$6 } $6 ~ /_WAIT/ { print "\033[0;34m"$5 " \033[01;32m"$6 } $6 ~ /TIME_WAIT/ { print "\033[0;34m"$5 " \033[01;32m"$6 } END { printf("%s","\033(B\033[m") } # Turn fancy formatting off' sleep 3 done 

To save your script in a variable and run it as bash -c "$cmd", you may combine command substitution and a here-document. If the label of a here-document is quoted (here, 'EOT'), its content is not expanded:

cmd=$(cat <<'EOT' netstat -tuplean | awk ' $6 ~ /ESTABLISHED/ { print "\033[0;31m" $5 " \033[01;31m"$6 } $6 ~ /_WAIT/ { print "\033[0;34m"$5 " \033[01;32m"$6 } $6 ~ /TIME_WAIT/ { print "\033[0;34m"$5 " \033[01;32m"$6 } END { printf("%s","\033(B\033[m") } # Turn fancy formatting off' EOT ) 
3
  • 2
    +1. writing this as a stand-alone script is a good way to avoid quoting issues due to the conflicting quoting requirements of watch and shell and the awk script. Commented Aug 13, 2021 at 14:18
  • What is \033(B escape code for? I've asked here What is the meaning of ESC ( B ANSI escape code? Commented Oct 24, 2022 at 16:21
  • @jcubic Honestly, I wouldn't know. Most likely I took that sequence from the output of tput, using a terminal emulator where TERM was set to xterm, without much thought on the meaning of every single character. Commented Oct 24, 2022 at 18:00
3

The command where you enclosed everything in single-quotes and properly escaped the old single-quotes is almost good. It prints "garbage" because you didn't use watch --color. Run this:

watch --color 'netstat -tuplean | awk '\''{NR>1; if( $6 ~ /ESTABLISHED/ ) print "\033[0;31m" $5 " \033[01;31m"$6 if ($6 ~ /_WAIT/ ) print "\033[0;34m"$5 " \033[01;32m"$6 if ($6 ~ /TIME_WAIT/ ) print "\033[0;34m"$5 " \033[01;32m"$6}'\' 

(Note the final '' in your original code is a single-quoted empty string concatenated with what's before. It changes nothing. My code omitted this useless '' completely.)

From man 1 watch:

-c, --color
Interpret ANSI color and style sequences.

1
  • .@Kamil: good point to you. Regarding the final ( ' ' ), I try to keep the logic: ( ' \ ' ' ) corresponding to the end of awk snippet and one last ( ' ) corresponding to close the watch command. Commented Aug 13, 2021 at 15:17

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.