Home > Blockchain >  Conditionally add a component to a shell pipeline
Conditionally add a component to a shell pipeline

Time:10-08

I want to conditionally add sort to a shell pipeline, but I'm getting a syntax error when I try:

want_sorting=0
generate_data() { for ((i=0; i<10; i  )); do echo "$RANDOM"; done; }
consume_data() {
  while IFS= read -r line; do
    echo "got data: $line"
  done
}

generate_data |
  if [ "$want_sorting" = 1 ]; then
    sort |
  fi
  consume_data

However, this throws a syntax error:

syntax error near unexpected token `fi'

How can I add sort | to the pipeline only if want_sorting is set?

CodePudding user response:

The problem with your code is that items are split into pipeline components, each of which has a different copy of the shell running it in parallel; so a single if statement can't have its fi split off into a different pipeline component.

You can't make a conditional pipeline entry easily, but you can easily make a pipeline entry decide whether to run a command that does something (like sort) or one that doesn't do anything at all (like cat).

generate_data |
  if [ "$want_sorting" = 1 ]; then
    sort -k1,1
  else
    cat
  fi |
  consume_data

Now, the slightly less-easy approach:

To get rid of this copy of cat one can use a shell function that only conditionally creates the pipeline component with sort before running whatever was supposed to come later in the pipe; something like:

maybe_sort_then() {
  if [ "$want_sorting" = 1 ]; then
    sort | "$@"
  else
    "$@"
  fi
}

generate_data |
  maybe_sort_then consume_data
  • Related