1

For example, suppose I define a variable:

DROP=

And I have a loop:

# highly compatible, streaming, 
# line-wise parser for embedded device
# no awk or external dependency
while IFS= read -r line; do

... generate_output_1 | xargs echo ... generate_output_2 | xargs echo ... generate_output_N | xargs echo

done <<<$(cleanFile x.txt) > "$OUTPUT_STREAM"

How would I toggle the ability to forward the output? I can think of defining a function, but is there a command that allows the output to be turned off or on?

# e.g. 
DROP=-d
generate_output | spigot ${DROP}

To address the comments, before asking this question, I used if statements. For those of you familiar with a streaming parser, avoiding if statements where possible is fundamentally important, since you tend to require if-statements in the body of the while loop already. So I'll go to some length to avoid any of the if statement solutions, including any control expressions (e.g. [ .. ] && ... || ...).

Secondly, I tried defining a PIPE variable:

if [ -z "$DROP" ]; then 
  PIPE=/dev/stdout
else
  PIPE=/dev/null
fi

And appended it in place of ... | xargs echo. This should have worked, intuitively. In practical terms, it did not work inside my while loop in my version of BASH and virtualization environment. That is because I've already used that technique in managing the output of my while loop. The final line of the example is making use of the technique already. In the OUTPUT_STREAM, I swap around files based on arguments or default to /dev/stdout:

done <<<$(cleanFile x.txt) > "$OUTPUT_STREAM"

What I am really looking for is a concise command that does what spigot does. And that is all.

Chris
  • 961
  • 7
  • 20
  • [ "x$DROP" = x ] && (generate_output_1 | xargs echo) : do a command only if $DROP is empty – Giacomo Catenazzi Aug 29 '23 at 14:52
  • 1
    Where should output go (if anywhere) if it's turned off? Similarly, where should it be directed if turned on? – Chris Davies Aug 29 '23 at 14:53
  • What do you want? Can you give an example? And none of the tools mentioned in the topic are native to linux, they go further back. – Henrik supports the community Aug 29 '23 at 14:53
  • I guess you want to write a script that changes the behaviour depending on $DROP. May be tell us: The script should be equivalent with while ...WHAT1 ... done when DROP is empty and with while...WHAT2.. done. Why is [ "x$DROP" = x ] && ... not useful?. – minorChaos Aug 29 '23 at 14:58
  • 2
    Do you look standard output redirection? -- like if [ "$DROP" = "--quiet" ]; then exec 1>/dev/null; fi – minorChaos Aug 29 '23 at 15:00
  • 1
    @minorChaos that's what I was considering too, but I wanted clarification before posting an answer – Chris Davies Aug 29 '23 at 16:10
  • 1
    or just [ -n "$DROP" ] && OUTPUT_STREAM=/dev/null before the while loop. Also, don't be so worried about awk or other external programs. Running external programs is shell's purpose. Most embedded systems have busybox installed, which includes a decent implementation of awk. And any version of awk is going to be much faster than a shell while read loop. BTW, see Why is using a shell loop to process text considered bad practice? and Understanding "IFS= read -r line" – cas Aug 30 '23 at 01:09
  • 1
    I'm not sure, but this looks essentially like this question: Conditional pipeline. The solutions there orbit around running one command or another based on a conditional, but that's also what your own answer does anyway, and that's what any command in place of spigot there would need to do. But there's also Stéphane Chazelas' answer using aliases to avoid a pass-through command. – ilkkachu Aug 30 '23 at 15:05
  • What exactly did you do with that conditionally set PIPE -variable? I can't tell from the post, but I wondered what would have been wrong with it. – ilkkachu Aug 30 '23 at 15:07
  • In any case, if the point is to join the lines of some output, xargs echo is not the right tool (chokes on quotes, backslashes, mangles spacing, may choke on lines starting with -, could output more than one line). Try paste -sd ' ' - instead. – Stéphane Chazelas Aug 30 '23 at 15:47

2 Answers2

1

No. There isn't. If I understand your need well, it would be easy to create such a command. As an example:

#include <stdio.h>
#include<signal.h>
#include<unistd.h>

int flag;

void sig_handler(int signum){ if (flag==1){flag=0;} else { flag=1;}

}

void main (){ int c; flag=1; signal(SIGHUP,sig_handler); while ((c=getchar())!=EOF){ if (flag==1) { putchar (c); } } }

My C is a bit rusty, so it may not be according to the latest coding standards, but this toggles output off and on when HUPped.

Ljm Dullaart
  • 4,643
  • love this, I'll see if I can make it work. Added the fix that worked for me in the interim. – Chris Aug 30 '23 at 14:42
0

I found that I couldn't use any work-arounds and instead had to define a function:

spigot(){
  if [ -z "$1" ]; then
    cat
  fi
}

... while ...

... | spigot $DROP

done

Chris
  • 961
  • 7
  • 20
  • 2
    It may be better to use a command that actually consumes its input in place of :, like cat >/dev/null. Otherwise, you force the left-hand side of your pipeline to receive a PIPE signal once it tries to write to the dead end of the pipe. – Kusalananda Aug 30 '23 at 14:46
  • 1
    If you want to pass the output through, run cat, rather than xargs echo, as the latter likely runs multiple processes and might mangle the output. And if you want to get rid of the output, run cat > /dev/null. – ilkkachu Aug 30 '23 at 15:10