Cmd with pipe, awk and quotes into watch - Stack Overflow

admin2025-04-18  3

Following this :

I want to put following line into watch cmd.

wc -l myfile | awk '{print "Done ",$1," of 587320"}'

Following above instructions I tried:

watch "wc -l myfile | awk '{print '"'Done '"',\$1,'"' of 587320'"'}'"

But got

awk: cmd. line:1: {print Done ,\, of 587320}
awk: cmd. line:1:              ^ backslash not last character on line
awk: cmd. line:1: {print Done ,\, of 587320}
awk: cmd. line:1:              ^ syntax error

Expected output :

Done  57776 of 587320

I'm overwhelmed by the quotes.

Following this : https://superuser.com/questions/276701/using-the-watch-command-with-an-argument-that-contains-quotes

I want to put following line into watch cmd.

wc -l myfile | awk '{print "Done ",$1," of 587320"}'

Following above instructions I tried:

watch "wc -l myfile | awk '{print '"'Done '"',\$1,'"' of 587320'"'}'"

But got

awk: cmd. line:1: {print Done ,\, of 587320}
awk: cmd. line:1:              ^ backslash not last character on line
awk: cmd. line:1: {print Done ,\, of 587320}
awk: cmd. line:1:              ^ syntax error

Expected output :

Done  57776 of 587320

I'm overwhelmed by the quotes.

Share Improve this question asked Jan 30 at 0:04 Gert GottschalkGert Gottschalk 4393 silver badges6 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 3
wc -l myfile | awk '{print "Done ",$1," of 587320"}'

You do not need wc -l as this can be done by GNU AWK itself, following way

awk 'END{print "Done ", NR, " of 587320"}' myfile

Explanation: END is executed after all files (in this case one file) is done, NR built-in variable holds The number of input records awk has processed since the beginning of the program’s execution

I'm overwhelmed by the quotes.

To avoid problem of this kind you might exploit -f option of GNU AWK, create file named counter.awk with following content

END{print "Done ", NR, " of 587320"}

and then you might get same result as above command doing

awk -f counter.awk myfile

which fit easily into watch command

watch "awk -f counter.awk myfile"

Note: I have tested above solution by running

for i in $(seq 1 100);
do
    echo $i >> myfile
    sleep 1
done

in other terminal and using watch version procps-ng 3.3.17 AND awk version GNU Awk 5.3.1

Escape the dollar sign and the double quotes, eg:

watch "wc -l myfile | awk '{print \"Done \",\$1,\" of 587320\"}'"

Alternatively, place the code in a script and no escapes are required, eg:

$ cat watch_me
#!/bin/bash

wc -l myfile | awk '{print "Done ",$1," of 587320"}'

$ watch ./watch_me


Running either of the above in terminal #1 against a 6-line file the following is displayed:

Every 2.0s: wc -l myfile | awk '{print "Done ",$1," of 587320"}'                                             ubu22b: Wed Jan 29 19:09:50 2025

Done  6  of 587320

In terminal #2 I added some lines to the file:

printf "7\n8\n9\n10\n" >> myfile

Terminal #1 then updated with:

Every 2.0s: wc -l myfile | awk '{print "Done ",$1," of 587320"}'                                             ubu22b: Wed Jan 29 19:09:50 2025

Done  10  of 587320

As @Daweo said, in your specific case you can rewrite the command to get rid of the | (and the quoting issues at the same time).

For complex cases, a solution can be to define a shell function, export it and use it with watch:

show_progress() {
    wc -l myfile |
    awk '{print "Done ",$1," of 587320"}';
}
export -f show_progress

watch show_progress

remark: watch runs your login shell, so the script shell and your login shell have to be the same, and that shell needs to be able to export functions.

转载请注明原文地址:http://www.anycun.com/QandA/1744944179a89832.html