Last active
June 14, 2023 18:15
-
-
Save nkh/718f897cef0bacc0b75da6254456e889 to your computer and use it in GitHub Desktop.
how to dynamically create a pipeline that handles options
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 : | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment