How to execute a command for each loop in awk?
Asked Answered
Q

2

9

I'm using awk to split a binary stream and I can get each part into a for loop like this.

for(i=1;i<=NF;i++)

I don't want to convert each field to text or arguments, but simply pass it directly to a command.

I'm trying to find something like this,

for(i=1;i<=NF;i++) system("decode")

but this obviously doesn't work. decode receives no input.

How do I get decode to receive each field in the loop?

Quentinquercetin answered 19/8, 2017 at 16:49 Comment(4)
Why are you using awk to call a shell tool instead of just doing this in shell? I suspect the answer is "because I'm doing more than this" and then whatever extra you are doing will drive the decision on the correct answer. So, post a complete script with sample input and expected output (i.e. a minimal reproducible example) so we can try to help you.Laminate
There's not much than what I've posted here frankly. I'm using awk because this is the only way I could manage to use multi-character delimiters. Also, most shell tools strip whitespace etc. making them a nightmare to work with binaryQuentinquercetin
What about avoiding awk and using pure shell? xargs -n1 decode < input_file.txt might do what you're looking for. Change $IFS if you don't want to split on white space.Illlooking
@Quentinquercetin shell tools do not strip whitespace. If that's happening to you then you're probably just forgetting to quote variables or not setting IFS= on a read or making some other mistake.Laminate
W
4

Doesn't this works for you?

for(i=1;i<=NF;i++) print $i | "decode"
close("decode")

It sends each field (or byte in your case) to a pipe connected to the "decode" program.

After that, close the "decode" pipe to force a flush of all the data on that pipe.

You can read more about gawk redirection on https://www.gnu.org/software/gawk/manual/html_node/Redirection.html

If you want to execute "decode" for each single byte, just close the pipe in each iteration:

for(i=1;i<=NF;i++) {
    print $i | "decode"
    close("decode")
}
Woke answered 19/8, 2017 at 18:48 Comment(5)
This calls decode just once with the entire stream of data. What I need is to call decode with each $iQuentinquercetin
I don't know what you really want to achieve here. If your file has 1Mbyte you'll be executing decode 1 million times. That makes no sense.Woke
Sorry, can you elaborate a little? For me, a few thousand calls is what I estimate.Quentinquercetin
I've edited my answer to add the code you're asking for. Execute decode for each binary byte. Hope it helps.Woke
thanks! the close did the trick. it needs the exact same string as the original command.Quentinquercetin
D
1

Is this what you are trying to do?

awk '{for(i=1; i<=NF; i++) system("decode "$i)}' input_file.txt

This should pass each field, contained in awk variable $i, to the decode external program. Mind the variable is outside the quotes for "decode ", or it would be interpreted by the shell instead of awk.

Distributive answered 21/8, 2017 at 20:27 Comment(2)
Close, but this still goes through the shell. I get an error like [sh: -c: line 1: unexpected EOF while looking for matching `"']. What I'd like is to pass data over stdin to decode, because the data is binary.Quentinquercetin
I see. Actually @Woke understood much better than I did. His|Her command seems to work for me, and to call the program for each field. Did you try enclosing the print and decode into a same set of curly braces? This is what I used: awk '{for(i=1;i<=NF;i++) {print $i | "decode"; close("decode")}}' input_fileDistributive

© 2022 - 2024 — McMap. All rights reserved.