Merge branch 'master' of ssh://git.uucp.hu/git/sysop/tools
[hband-tools.git] / bash / bash-utils
blob7b032e3614e07100649ec922f4167e69ce1f1770
1 #!/bin/bash
3 pipe()
5 if [ "$1" = --help ]
6 then
7 echo "NAME"
8 echo " pipe - mimic pipe(2) syscall in shell"
9 echo "INVOCATION"
10 echo " pipe <READER_VAR> <WRITER_VAR>"
11 echo "DESCRIPTION"
12 echo " Create anonymous pipe."
13 echo " Reader end's file descriptor stored in variable name in the first argument."
14 echo " Writer end's file descriptor stored in variable name in the second argument."
15 echo "EXAMPLE"
16 echo " pipe read_fd write_fd"
17 echo " echo Lorem ipsum >&\$write_fd"
18 echo " read -u \$read_fd data"
19 echo " echo \$data # => Lorem ipsum"
20 return
23 local pid1 pid2 myin myout lnk0 lnk1
24 [ "$1" = rdr ] || local rdr
25 [ "$2" = wtr ] || local wtr
27 myin=`readlink /proc/self/fd/0`
28 myout=`readlink /proc/self/fd/1`
30 # calling sleep(1) via env to avoid bash's built-in sleep which may not know 'inf'.
31 env sleep inf | env sleep inf &
32 pid2=$!
33 pid1=$(jobs -p %+)
35 while true
37 lnk0=`readlink /proc/$pid2/fd/0`
38 lnk1=`readlink /proc/$pid1/fd/1`
39 if [ "$lnk0" != "$myin" -a "$lnk1" != "$myout" ]
40 then
41 break
43 done
45 exec {wtr}>/proc/$pid1/fd/1 {rdr}</proc/$pid2/fd/0
47 disown $pid2
48 kill -KILL $pid1 $pid2 # sometimes INT and TERM are blocked, but it's safe to kill such a no-op process
50 eval $1=$rdr
51 eval $2=$wtr
54 close()
56 if [ "$1" = --help ]
57 then
58 echo "NAME"
59 echo " close - mimic close(2) syscall in shell"
60 echo "INVOCATION"
61 echo " close <FD_1> [FD_2 [FD_3 [...]]]"
62 echo "DESCRIPTION"
63 echo " Close file descriptor(s) given in arguments."
64 echo "EXAMPLE"
65 echo " pipe read_fd write_fd"
66 echo " close \$write_fd"
67 return
70 local fd
71 for fd in "$@"
73 #eval "exec $fd>&-"
74 exec {fd}>&-
75 done
78 capture2()
80 if [ "$1" = --help ]
81 then
82 echo "NAME"
83 echo " capture2 - store a command's stdout and stderr in separated variables"
84 echo "INVOCATION"
85 echo " capture2 <COMMAND> [<ARGS>]"
86 echo "DESCRIPTION"
87 echo " Capture <COMMAND>'s stdout and stderr in separated shell variables"
88 echo " without running it twice."
89 echo " Store stdout and stderr data in script-global variables"
90 echo " called \$capture2_stdout and \$capture2_stderr respectively."
91 echo "EXAMPLE"
92 echo " capture2 ls -lRA /etc"
93 echo " echo output was "'\$capture2_stdout'""
94 echo " echo error was "'\$capture2_stderr'""
95 echo "RETURN VALUE"
96 echo " <COMMAND>'s exit status"
97 echo "VARIABLES"
98 echo " using the following script-global variables"
99 echo " - capture2_stdout"
100 echo " - capture2_stderr"
101 echo "CAVEAT"
102 echo " May not work on large output, depend on fifo buffer size."
103 echo "SEE ALSO"
104 echo " pipe(1bash) close(1bash)"
105 return
108 local x r w
109 pipe r w
110 capture2_stdout=$("$@" 2>&$w)
111 x=$?
112 close $w
113 capture2_stderr=$(cat <&$r)
114 close $r
115 return $x
118 is_digit()
120 [ "$1" = 0 -o "$1" = 1 -o "$1" = 2 -o "$1" = 3 -o "$1" = 4 -o "$1" = 5 -o "$1" = 6 -o "$1" = 7 -o "$1" = 8 -o "$1" = 9 ]
123 is_number()
125 [ "$1" -ge 0 -o "$1" -lt 0 ] 2>/dev/null
128 is_alpha()
130 expr "$1" : '[a-zA-Z]\+$' >/dev/null 2>&1
133 warnx()
135 true "warnx - mimic warnx(3) in shell"
136 echo "${0##*/}: $*" >&2
139 errx()
141 true "errx - mimic errx(3) in shell"
142 errno=$1
143 shift
144 warnx "$@"
145 exit $errno
148 bash_isset()
150 local sets=${2:-$-}
151 sets=${sets//[!$1]/}
152 echo ${sets:-_}
155 bash_defined()
157 [ "${!1+x}" = x ]
160 bash_trapbody()
162 local a
163 a=`trap -p "$1"`
164 if [ -z "$a" ]
165 then
166 echo -
167 return
169 a=${a:9}
170 a=${a:0:-${#1}-2}
171 echo "$a"
174 try()
176 declare -g TRYSTACK
177 local savesets=$-
178 TRYSTACK+=($(bash_isset e $savesets)$(bash_isset E $savesets)"$(bash_trapbody ERR)")
179 trap - ERR
181 while [ -n "$1" ]
183 case "$1" in
184 --except)
185 shift
186 trap "$1" ERR
189 echo "Unknown option: $1" >&2
190 set -o errexit
191 false
193 esac
194 shift
195 done
197 set -o errexit
198 set -o errtrace
201 untry()
203 local trydata
204 trydata=${TRYSTACK[-1]}
205 unset TRYSTACK[${#TRYSTACK[@]}-1]
206 [ "${trydata:0:1}" = _ ] && set +o errexit || set -o errexit
207 [ "${trydata:1:1}" = _ ] && set +o errtrace || set -o errtrace
208 trap "${trydata:2}" ERR
209 return 0
212 fixerrexit()
214 ( eval "expr '$-' : '.*e' >/dev/null && set -e; $*"; )
217 template()
219 cat "$@" |\
221 local rline tvar var replace sedexpr
222 while read -r
224 rline=$REPLY
225 sedexpr=""
226 { grep -Eo '%[a-zA-Z0-9\./_-]+%' <<<"$rline" || true; } |\
227 sort -u |\
229 while read tvar
231 # strip percent marks
232 var=${tvar:1:-1}
233 # resolve bash variable
234 replace=${!var}
235 # avoid backrefs
236 replace=${replace//\\/\\\\}
237 # avoid whole match backref
238 replace=${replace//&/\\&}
239 # compose sed expression like: s@%user\.name%@joe@g;s@%user\.email%@joe\@local@g;
240 sedexpr="${sedexpr}s@${tvar//\./\\.}@${replace//@/\@}@g;"
241 done
242 # action
243 sed -e "$sedexpr" <<<"$rline"
245 done
249 errorlevel()
251 return $1
254 bash_join()
256 local IFS=$1
257 shift
258 echo "$*"
261 in_list()
263 local needle=$1
264 local hay
265 shift
266 for hay in "$@"
268 if [ ".$hay" = ".$needle" ]
269 then
270 return 0
272 done
273 return 1
276 array_shift()
278 if [ "$1" = --help ]
279 then
280 echo "NAME"
281 echo " array_shift - print and remove the first element from a bash indexed array"
282 echo "INVOCATION"
283 echo " array_shift <VARNAME>"
284 return
287 local array_name=$1
288 local aux
289 eval "aux=\${$array_name[0]}"
290 unset $array_name[0]
291 eval "$array_name=(\"\${$array_name[@]}\")"
292 echo "$aux"
295 array_reverse()
297 if [ "$1" = --help ]
298 then
299 echo "NAME"
300 echo " array_reverse - reverse a bash array elements"
301 echo "INVOCATION"
302 echo " array_reverse <VARNAME>"
303 return
306 local array_name=$1
307 local i ci len aux
308 eval "len=\${#$array_name[@]}"
309 for ((i=0; i<len/2; i++))
311 ci=$[len-i-1]
312 eval "aux=\${$array_name[$i]}"
313 eval "$array_name[$i]=\${$array_name[$ci]}"
314 eval "$array_name[$ci]=\$aux"
315 done
318 bash_scriptdir()
320 dirname "$(readlink -f "${BASH_SOURCE[-1]}")"
323 ECHO()
325 printf %s "$*"