#!/bin/bash

echo process a given input depending on options in a pipeline
echo -------------------------------------------------------------------------------- 
echo
 
inputs=("2 xxx" "1 hi" "3 abc")

# options to sort or limit the number of answers
opt_sort=1
opt_limit=2

declare -p inputs
declare -p opt_sort opt_limit

echo -------------------------------------------------------------------------------- 
echo solution 1: manually check the option 
echo

printf '%s\n' "${inputs[@]}" | 
	# we can use an if
	if [ "$opt_limit" -gt 0 ]; then grep -m "$opt_limit" -P '^' ; else cat; fi |
	# or a more concise block
	{ ((opt_sort)) && sort || cat ; } |
	sed -e 's/xxx/XXX/' 

echo -------------------------------------------------------------------------------- 
echo solution 2: use function that pipe to each other 
echo

# we can declare functions which will handle the option
# the functions are chained in the call, depending on the option
# run the process and pipe to the chained commands or run the 
# chained command

do_limit() { (($opt_limit))   && head -n "$opt_limit" | "$@" || "$@" ; }
do_sort() { ((opt_sort)) && sort | "$@" || { [[ -n "$@" ]] && "$@" ; } ; }

# a function with a simple operation, no option handles
do_sed() { sed -e 's/xxx/XXX/' ; }

printf '%s\n' "${inputs[@]}" | do_limit do_sort do_sed
printf '%s\n' "${inputs[@]}" | do_limit do_sort cat | do_sed

# the last option handling function needs a chained function
# this wouldn't work
# printf '%s\n' "${inputs[@]}" | do_limit do_sort

echo -------------------------------------------------------------------------------- 
echo solution 3: create a function that runs a list of option handling functions
echo

do_all() { do_limit do_sort do_sed ; }
printf '%s\n' "${inputs[@]}" | do_all
printf '%s\n' "${inputs[@]}" | do_all | do_sed

echo -------------------------------------------------------------------------------- 
echo solution 4: use list of commands, call directly 
echo


# creating option handling functions with all the piping can be simplified
create() { eval "$1() { $2 | \"\$@\" || \"\$@\" ; }" ; }

# create another function that handle $opt_limit
#  equivalent to do_limit() { (($opt_limit))   && head -n "$opt_limit" | "$@" || "$@" ; }
create do_limit2 '(($opt_limit)) && head -n "$opt_limit"'

# we can put all the commands in a list
commands=(do_limit2 do_sort)

# this function will al the commands in the above list
do_commands() { "${commands[@]}" cat ; }
printf '%s\n' "${inputs[@]}" | do_commands
printf '%s\n' "${inputs[@]}" | do_commands | do_sed

echo -------------------------------------------------------------------------------- 
echo solution 5: use list of commands, pass them as arguments 
echo

# we can also define a function that accepts a list of commands to run
do_command_list() { "$@" cat ; }

# the commands are passed as arguments
printf '%s\n' "${inputs[@]}" | do_command_list "${commands[@]}"
printf '%s\n' "${inputs[@]}" | do_command_list "${commands[@]}" | do_sed

echo -------------------------------------------------------------------------------- 
echo solution 6: use list of commands, pass the list 
echo

# we can also define a function that takes a list by name
do_command_list_by_name() { local -n array=$1 ; "${array[@]}" cat ; }

# we pass the list name
printf '%s\n' "${inputs[@]}" | do_command_list_by_name commands
printf '%s\n' "${inputs[@]}" | do_command_list_by_name commands | do_sed


echo -------------------------------------------------------------------------------- 
echo solution 7: use list of commands, use temporary files
echo

run_commands() 
{
PIPE1=$(mktemp) PIPE2=$(mktemp)

>$PIPE1 cat 

for f in "$@"
	do
		>$PIPE2 ; <$PIPE1 $f >$PIPE2 || <$PIPE1 cat >&$PIPE2
		t=$PIPE1 PIPE1=$PIPE2 PIPE2=$t
	done

<$PIPE1 cat
}

echo -------------------------------------------------------------------------------- 
echo solution 8: eval pipes 
echo

opt_limit=2 ; run_limit() { ((opt_limit)) && head -n "$opt_limit" ; }

opt_sort=1 ; run_sort() { ((opt_sort)) && sort ; }

pipe() { p="cat $(printf "| { %s || cat ; } " "$@")" ;  eval "$p" ; }

printf '%s\n' "2 xxx" "1 hi" "3 abc" |  pipe run_limit run_sort

echo -------------------------------------------------------------------------------- 
echo solution 9: eval pipes from array
echo


pipe_list() { p="cat $(printf "| { %s || cat ; } " "${run_list[@]}")" ;  eval "$p" ; }

run_list=(run_limit run_sort)

printf '%s\n' "2 xxx" "1 hi" "3 abc" |  pipe_list 

echo -------------------------------------------------------------------------------- 
echo solution 10: eval pipes from array passed as argument
echo

pipe_list_arh() { local -n list=$1 ; p="cat $(printf "| { %s || cat ; } " "${list[@]}")" ;  eval "$p" ; }

printf '%s\n' "2 xxx" "1 hi" "3 abc" |  pipe_list run_list

# vim: set filetype=bash :