public
Last active

Some testcases for concurrent background jobs and pipe I/O

  • Download Gist
out
1 2 3 4 5 6
a: 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2 1 2 1=16 2=14
b: 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1 2 1 2 1 2 1=14 2=16
c: 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1=15 2=15
d: 2 1 1 2 1 2 1 1 2 1 2 1 2 1 1 2 1 1 2 1 2 1 1 2 1 2 1 1 2 1 1=18 2=12
e: 3 2 3 2 3 2 3 2 3 2 3 2 3 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 3 2 2=14 3=16
f: 2 2 1 2 1 2 1 2 1 2 2 1 2 1 2 1 1 2 1 2 1 2 2 1 2 1 2 1 2 1 1=14 2=16
pipefork.bash
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
#!/usr/bin/env bash
 
function compatFixes {
${BASH_VERSION+shopt -s extglob lastpipe}
 
if [[ ${!KSH_VERSION} == .sh.version ]]; then
function read {
command read "${@/#*(-[^a])a*(?)/\1A\2}"
}
fi
}
 
# Functions share a stream of zeros.
function zeros {
printf '%.s0' {1..30}
}
 
# Reader function.
function z {
typeset -li x=
while IFS= read -rN1 _; do
((x++))
printf %-2d "$1" # keep track of which job this is.
done
}
 
# read, format, print output from z jobs
function out {
typeset -lia totals=() zs=()
read -ra zs
printf %-2s "${zs[@]}"
 
typeset -li x=
for x in "${zs[@]}"; do
((totals[x]++))
done
 
printf %s "${clrs[green]}"
for x in "${!totals[@]}"; do
printf '%s=%s ' "$x" "${totals[x]}"
done
printf '%s\n' "${clrs[reset]}"
}
 
### example funcs ###
 
# For some reason Bash doesn't require an explicit <&0 in this case.
function a {
out < <({ z 1 & z 2; } < <(zeros))
}
 
# As above, with piped output.
function b {
{ z 1 <&0 & z 2; } < <(zeros) | out
}
 
# Same as b.
function c {
zeros | { z 1 <&0 & z 2; } | out
}
 
# Like the above two. Redirect to each z individually. Now behaves as the first example again.
function d {
typeset x
{ z 1 <&$x & z 2 <&$x; } {x}< <(zeros) | out
}
 
# The first command in the list to be explicitly redirected to the proper input,
# and all subsequent members, are asynchronous as expected.
function e {
typeset x
{ z 1 & z 2 <&$x & z 3 & } {x}< <(zeros) <&$x | out
}
 
# Pass the name of the pipe to g and individually redirect to z. Doesn't work.
# Pipe is closed before the second call to f sees it:
function f {
function g { z 1 & z 2; } <"$1"
g <(zeros) | out
unset -f g
}
 
function main {
compatFixes
 
typeset -A clrs=(
[green]="$(tput setaf 2)"
[reset]="$(tput sgr0)"
)
 
typeset fn
for fn; do
printf '%s: ' "$fn"
"$fn"
done
}
 
main {a..f}
 
# vim: set fenc=utf-8 ff=unix ts=4 sts=4 sw=4 ft=sh et:

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.