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?

akula1001
  • 4,576
  • 12
  • 43
  • 56
  • 1
    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 [mcve]) so we can try to help you. – Ed Morton Aug 19 '17 at 20:07
  • 1
    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 binary – akula1001 Aug 21 '17 at 16:32
  • 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. – Adam Katz Aug 23 '17 at 15:09
  • @akula1001 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. – Ed Morton Aug 24 '17 at 19:08

2 Answers2

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")
}
valrog
  • 216
  • 1
  • 6
  • This calls decode just once with the entire stream of data. What I need is to call decode with each $i – akula1001 Aug 21 '17 at 16:52
  • 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. – valrog Aug 22 '17 at 08:42
  • Sorry, can you elaborate a little? For me, a few thousand calls is what I estimate. – akula1001 Aug 23 '17 at 03:21
  • I've edited my answer to add the code you're asking for. Execute decode for each binary byte. Hope it helps. – valrog Aug 23 '17 at 08:00
  • thanks! the close did the trick. it needs the exact same string as the original command. – akula1001 Sep 26 '17 at 18:24
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.

Qeole
  • 8,284
  • 1
  • 24
  • 52
  • 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. – akula1001 Aug 21 '17 at 20:41
  • I see. Actually @valrog 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_file` – Qeole Aug 21 '17 at 21:12