Using Output of Awk to Run Command

Using output of awk to run command

Use system from within awk:

awk '{ system("openssl s_client -connect host:port -cipher " $1) }' ciphers.txt

Execute awk output

| bash does the trick...

while read line;
do
awk '/ differ$/ {print "diff "$2" "$4" > "$2".diff"}{}' | bash;
done < diffs.txt

Assigning system command's output to variable

Figured out.

We use awk's Two-way I/O

{
"strip $1" |& getline $1
}

passes $1 to strip and the getline takes output from strip back to $1

Execute bash command inside awk and print command output

Just do the string reversal and translation in awk itself:

$ awk '
BEGIN {
old="ATGC"
new="TACG"
for (i=1;i<=length(old);i++) {
tr[substr(old,i,1)] = substr(new,i,1)
}
}
{
newVar=""
for (i=1;i<=length($3);i++) {
char = substr($3,i,1)
newVar = (char in tr ? tr[char] : char) newVar
}
print $1, $2, newVar, $4
}
' file
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK

If you really feel a burning need to call an external tool from awk and read the result back that'd be:

$ awk '
{
cmd="echo \047" $3 "\047 | rev | tr \047ATGC\047 \047TACG\047"
newVar=((cmd | getline line) > 0 ? line : "failed")
close(cmd)
print $1, $2, newVar, $4
}
' file
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK

but you should expect a significant performance hit from doing that and see also the getline caveats: http://awk.freeshell.org/AllAboutGetline.

Run Shell Command Inside Awk only Once 'per command' Using System(), i e, print only Once text

Primary issue (repeated text/text2 entries on stdout) comes from what appears to be a dual use of the awk variable k and some missing input control.

The awk variable k is being used as an auto-incremented index by the 2nd and 3rd gsub(... k++ ...) calls; at no point is k reset to 0 (or 1) so logically speaking OPs k==1 tests should only occur once. However ...

The tests for k==1 will occur for every input line (from all files) ... this occurs for lines with and without the home_cool string; and because there are two k==1 tests being validated for each input line OP is going to get double outputs (text and text2) as long as k==1.

Also keep in mind that k is only being incremented (by the gsub() calls) for lines with the string home_cool; net result is lines without home_cool will see k==1 unchanged so the two k==1 tests will fire for these lines, too; we'll get extra text/text2 entries on stdout until the next gsub() fires and increments k (via the k++)


I'd suggest using a different variable (eg, p) to determine when to print the text/text2 entries, and moving the k==1 tests (now if (p)) to a location where they are only run when appropriate.

One idea for a rewrite:

awk '
FNR==1 {++f; p=1} # reset our "p"rintme? flag for each new file

f==1 {a[i++]=$0}

f==2 {if ($0~/home_cool/)
{gsub(/home_cool/, a[int(j++/2)%2]) }
print > "2.txt"
}

f==3 {if ($0~/home_cool/)
{gsub(/home_cool/, a[int(k++/2)%3 + 2])}
if (p) # old "k==1" test; if "p"rintme flag set then ...
{print "text"; system("sleep 4"); p=0} # print, sleep, clear flag
print > "3.txt"
}

f==4 {if ($0~/home_cool/)
{gsub(/home_cool/, a[int(k++/2)%3 + 2])}
if (p) # old "k==1" test; if "p"rintme flag set then ...
{print "text2"; system("sleep 4"); p=0} # print, sleep, clear flag
print > "4.txt"
}
' 1.txt 0.txt 0-1.txt 0-2.txt

When run this generates the following on stdout:

text
text2

NOTES:

  • other than the print issues I'm assuming OP's logic is correct (ie, the contents of the [234].txt files are correct)
  • if an input file is empty then the associated f==? test will not fire which means ...
  • the associated if (p)... test/operation will not fire;
  • for example ...
  • if 0-2.txt is empty then f==4 will never test as positive so ...
  • the associated if (p) ... print "text2" ... will not fire
  • it's not clear (to me) if OP needs to conditionally print the text/text2 messages if the corresponding files are empty ...
  • easy enough to modify the code but I'll skip that for now so as to limit the confusion

How can I pass variables from awk to a shell command?

you are close. you have to concatenate the command line with awk variables:

awk '{system("wc "$1)}' myfile

awk: how to execute a command and read its output

Just in case there's yet another getline caveat kicking in here (see http://awk.info/?tip/getline), try closing the pipe after every invocation, e.g.:

ping eulbi001 |
awk -F'[ =]' 'BEGIN{cmd="date +%s"} /64 bytes/{cmd|getline D; close(cmd); print D,$11}'

and see if you get different results. You still shouldn't expect D to change on every invocation though, just every second. You could add a ".%N" for smaller granularity of your timestamps if you like.

Better yet, use GNU awk with it's builtin time functions so you don't need to deal with this stuff at all.



Related Topics



Leave a reply



Submit