Bash functional: Difference between revisions
From wikinotes
No edit summary |
No edit summary |
||
(16 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Fancy loops that let you process things incrementally in a pipeline.<br> | Fancy loops that let you process things incrementally in a pipeline.<br> | ||
You'll almost never use these directly, but it might be inspiration for a more useful function. | You'll almost never use these directly, but it might be inspiration for a more useful function. | ||
{{ NOTE | | |||
If your callable accepts parameter as stdin, you don't need map/filter (ex. sed/grep work just fine from stdin).<br> | |||
you could also use xargs to pass stdin lines as callable params. | |||
}} | |||
= Filter = | = Filter = | ||
<blockquote> | <blockquote> | ||
< | <syntaxhighlight lang="bash"> | ||
# | # Call callable/params($*), passing each each STDIN line as the last parameter | ||
# | |||
# EXAMPLE: | |||
# divisible_by_2() { [ $(($1 % 2)) -eq 0 ] } | |||
# echo {1..10} | tr ' ' '\n' | filter divisible_by_2 | |||
</ | # #> 2 | ||
# #> 4 | |||
# #> ... | |||
# | |||
filter() { | |||
local input | |||
while read -r input; do | |||
if "$@" "${input}" 2>&1 > /dev/null ; | |||
echo "${input}" | |||
fi | |||
done | |||
} | |||
</syntaxhighlight> | |||
</blockquote><!-- Filter --> | </blockquote><!-- Filter --> | ||
= Map = | = Map = | ||
<blockquote> | <blockquote> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Call callable/params($*), passing each each STDIN line as the last parameter | |||
# | |||
# EXAMPLE: | |||
# print_divisible_by_2() { | |||
# [ $(($1 % 2)) -eq 0 ] && echo "$1:yes" || echo "$1:no" | |||
# } | |||
# echo {1..10} | tr ' ' '\n' | map print_divisible_by_2 | |||
# #> 1:no | |||
# #> 2:yes | |||
# #> ... | |||
# | |||
map() { | map() { | ||
local input | local input | ||
Line 29: | Line 54: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Map --> | </blockquote><!-- Map --> | ||
= Reduce = | = Reduce = | ||
<blockquote> | <blockquote> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# callable/params must accept aggregate as 2nd-last param, and input as last param. | |||
# | |||
# EXAMPLE: | |||
# sum() { echo $(($1 + $2)) } | |||
# echo {1..10} | tr ' ' '\n' | reduce sum 0 | |||
# #> 55 | |||
# | |||
reduce() { | reduce() { | ||
local input | local input | ||
local callable="${@:1:-1}" # all until last param | |||
local aggregate="${@[-1]}" # last param | |||
while read -r input; do | while read -r input; do |
Latest revision as of 19:45, 11 December 2022
Fancy loops that let you process things incrementally in a pipeline.
You'll almost never use these directly, but it might be inspiration for a more useful function.
NOTE:
If your callable accepts parameter as stdin, you don't need map/filter (ex. sed/grep work just fine from stdin).
you could also use xargs to pass stdin lines as callable params.
Filter
# Call callable/params($*), passing each each STDIN line as the last parameter # # EXAMPLE: # divisible_by_2() { [ $(($1 % 2)) -eq 0 ] } # echo {1..10} | tr ' ' '\n' | filter divisible_by_2 # #> 2 # #> 4 # #> ... # filter() { local input while read -r input; do if "$@" "${input}" 2>&1 > /dev/null ; echo "${input}" fi done }
Map
# Call callable/params($*), passing each each STDIN line as the last parameter # # EXAMPLE: # print_divisible_by_2() { # [ $(($1 % 2)) -eq 0 ] && echo "$1:yes" || echo "$1:no" # } # echo {1..10} | tr ' ' '\n' | map print_divisible_by_2 # #> 1:no # #> 2:yes # #> ... # map() { local input while read -r input; do "$@" "${input}" done }
Reduce
# callable/params must accept aggregate as 2nd-last param, and input as last param. # # EXAMPLE: # sum() { echo $(($1 + $2)) } # echo {1..10} | tr ' ' '\n' | reduce sum 0 # #> 55 # reduce() { local input local callable="${@:1:-1}" # all until last param local aggregate="${@[-1]}" # last param while read -r input; do aggregate="$("${callable[@]}" "${aggregate}" "${input}")" done echo "${aggregate}" }