Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return two variables in awk

Tags:

bash

shell

awk

At the moment here is what im doing

ret=$(ls -la | awk '{print $3 " "  $9}')
usr=$(echo $ret | awk '{print $1}')
fil=$(echo $ret | awk '{print $2}')

The problem is that im not running an ls im running a command that takes time, so you can understand the logic.

Is there a way I can set the return value to set two external values, so something such as

ls -la | awk -r usr=x -r fil=y '{x=$3; y=$9}'

This way the command will be run once and i can minimize it to one line

like image 445
Angel.King.47 Avatar asked Jan 25 '12 11:01

Angel.King.47


2 Answers

It's not pretty, but if you really need to do this in one line you can use awk/bash's advanced meta-programming capabilities :)

eval $(ls -la | awk '{usr = $3 " " usr;fil = $9 " " fil} END{print "usr=\""usr"\";fil=\""fil"\""}')

To print:

echo -e $usr
echo -e $fil

Personally, I'd stick with what you have - it's much more readable and performance overhead is tiny compared to the above:

$time <three line approach>

real    0m0.017s
user    0m0.006s
sys     0m0.011s

$time <one line approach>
real    0m0.009s
user    0m0.004s
sys     0m0.007s
like image 59
bob Avatar answered Sep 19 '22 04:09

bob


A workaround using read

usr=""
fil=""
while read u f; do usr="$usr\n$u"; fil="$fil\n$f"; done < <(ls -la | awk '{print $3 " "  $9}')

For performance issue you could use <<<, but avoid it if the returned text is large:

while read u f; do usr="$usr\n$u"; fil="$fil\n$f"; done <<< $(ls -la | awk '{print $3 " "  $9}')

A more portable way inspired from @WilliamPursell's answer:

$ usr=""
$ fil=""
$ while read u f; do usr="$usr\n$u"; fil="$fil\n$f"; done << EOF
> $(ls -la | awk '{print $3 " "  $9}')
> EOF
like image 38
oHo Avatar answered Sep 19 '22 04:09

oHo