简体   繁体   中英

How to run a shell command inside AWK that takes AWK variables as the input?

My package manager has a option --dry-run or -n that shows what packages will be installed when I do a update -u .

It outputs in the following format <pkgver> <action> <arch> <repository> <installedsize> <downloadsize> ,

~ $ xbps-install -un | head -n 5
MesaLib-devel-20.1.4_1 update x86_64 https://alpha.de.repo.voidlinux.org/current 148212 35909
amdvlk-2020.Q3.2_1 update x86_64 https://alpha.de.repo.voidlinux.org/current 53003388 17077076
audacious-4.0.5_1 configure x86_64 https://alpha.de.repo.voidlinux.org/current 2016807 578996
libwavpack-5.3.0_1 configure x86_64 https://alpha.de.repo.voidlinux.org/current 174280 86184
libfluidsynth-2.1.3_1 configure x86_64 https://alpha.de.repo.voidlinux.org/current 448560 216298

I want to know only two things, the packages that are bigger than a MiB. The download size is in column 5, so, I did the following to get in human readable format, filter through grep and pretty print.

~ $ xbps-install -un | numfmt --field=5 --to=si | grep -P '\d+M' | awk '{printf("%30s%7s\n",$1,$5);}' | head -n 5
        amdvlk-2020.Q3.2_1    54M
         audacious-4.0.5_1   2.1M
 audacious-plugins-4.0.5_1   6.2M
           openvdb-7.0.0_1   9.2M
          alembic-1.7.13_1   3.0M

This works great. I want to make it shorter. I know has awk (mine is gawk) has a inbuilt PCRE, so I can get rid of grep. But when I try this, I get nothing.

   ~ $ xbps-install -un | numfmt --field=5 --to=si | awk '$5==/\d+M/ {printf("%30s%7s\n",$1,$5);}'

But awk throws me an error saying,

   awk: cmd. line:1: warning: regexp escape sequence `\d' is not a known regexp operator

I thought gawk supported PCRE, but apparently it doesn't. So, I replace \d+ with [0..9]+ . I get no error, but no output. Please help fix the error. Is there a way to run a command inside AWK? Something like this

   ~ $ xbps-install -un | awk '$5>1024 { print $1 `numfmt --to=si $5`; }

Is this even possible? Even in Perl/PHP?

EDIT: I'm sorry I asked the question in a wrong way. My main question was if there is a way to expand shell commands in AWK with AWK variables. For example, in bash shell commands can be expanded as below,

   ~ $ file `which python`
   ~ $ file $(which python)
   ~ $ file (which python)       # in fish

Similarly, I want to numfmt a awk variable, $5 like numfmt --to=iec $5 . So, I was wondering if I can do something like

   ~ $ xbps-install -un | awk '$5>1024 { print $1 `numfmt --to=si $5`; }

Your awk just needs to be written as below. And \d is a PCRE digit pattern which is not/never supported in GNU Awk. Pipe the output of numfmt to below

awk '$5 ~ /M$/{ printf("%30s%7s\n", $1, $5) }'

which means, match those columns in $5 whose last character ends with an M which would be the converted SI units in MB

The pattern below is wrong, because the == brings in literal string "equality" check in Awk, which you have intermingled with an incorrect PCRE construct.

awk '$5==/\d+M/'

Also the range expressions need to be written as [0-9] and not [0..9] .


For the updated question, for which OP wants to use numfmt inside awk , for which I don't see a reason as they can very well pipe the output of numfmt to awk .

If you want to run the numfmt command inside awk , you can use the getline function in awk

awk '$5 > 1024 { cmd = "numfmt --to=si " $5; print $1, ((cmd | getline res)>0)? res : $5; close(cmd) }'

This approach is not needed as your original cmd | numfmt | awk cmd | numfmt | awk cmd | numfmt | awk approach is very well valid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM