Revision 3774
Added by Aaron Marcuse-Kubitza over 12 years ago
expand_braces | ||
---|---|---|
1 | 1 |
#!/bin/bash |
2 | 2 |
# Expands bash-style {} expressions. |
3 | 3 |
# See <http://www.gnu.org/software/bash/manual/bash.html#Brace-Expansion>. |
4 |
# Usage: [env expand_braces_debug=1] self <in >out |
|
4 | 5 |
# Filters each line from stdin to stdout. |
5 | 6 |
# Warning: Due to shell limitations, a blank line will be interpreted as EOF. |
6 | 7 |
|
... | ... | |
10 | 11 |
|
11 | 12 |
echoEach () { local line; for line in "$@"; do echo "$line"; done; } |
12 | 13 |
|
14 |
replaceRecursive () |
|
15 |
{ |
|
16 |
local sedExpr="$1" str="$2" prevStr |
|
17 |
while true; do |
|
18 |
prevStr="$str" |
|
19 |
str="$(echo "$str"|sed -e "$sedExpr")" |
|
20 |
test "$str" = "$prevStr" && break # done if nothing replaced |
|
21 |
done |
|
22 |
echo "$str" |
|
23 |
} |
|
24 |
|
|
25 |
debug () |
|
26 |
{ |
|
27 |
local label="$1" str="$2" |
|
28 |
test -n "$expand_braces_debug" && (echo "** $label:"; echo "$str") >&2 |
|
29 |
} |
|
30 |
|
|
13 | 31 |
singleQuote="'" |
14 | 32 |
singleQuoteEsc="'\''" |
15 | 33 |
CR=$'\r' |
16 | 34 |
LF=$'\n' |
17 |
braceKeep='./{'
|
|
18 |
bracketKeep='{*[*,*]*}'
|
|
35 |
nonBracket="[^][]*" # matches non-[] chars
|
|
36 |
brackets="($nonBracket\[$nonBracket\])*$nonBracket"
|
|
19 | 37 |
|
20 | 38 |
while true; do |
21 | 39 |
read # get next line from stdin; strips trailing newlines |
22 | 40 |
line="$REPLY" |
23 | 41 |
test -z "$line" && break # EOF if no line or empty line |
24 | 42 |
|
25 |
if test "${line/$braceKeep/}" != "$line" \ |
|
26 |
-o "${line/$bracketKeep/}" != "$line"; then # line contains unparseable exprs |
|
27 |
echo "$line" # don't expand |
|
28 |
else |
|
29 |
line="${line//$CR/}" # remove \r |
|
30 |
line="${line//$singleQuote/$singleQuoteEsc}" # escape single quotes |
|
31 |
line="$(echo "$line"|sed -e "s/[^{,}]+/'&'/g")" # escape non-brace chars |
|
32 |
|
|
33 |
eval echoEach $line # brace-expand $line |
|
34 |
fi |
|
43 |
line="${line//$CR/}" # remove \r |
|
44 |
origLine="$line" |
|
45 |
debug orig "$line" |
|
46 |
|
|
47 |
line="${line//$singleQuote/$singleQuoteEsc}" # escape single quotes |
|
48 |
line="$(echo "$line"|sed -e "s/[^{,}]+/'&'/g")" # escape non-brace chars |
|
49 |
# Escape commas inside [], which should not be used for {}. |
|
50 |
# Note that '' around "," are closing and opening the escaped string, |
|
51 |
# not the other way around. |
|
52 |
line="$(replaceRecursive "s/(\[$nonBracket)','/\1,/g" "$line")" # innermost |
|
53 |
# Also support one level of nesting, which is the most we currently use. |
|
54 |
line="$(replaceRecursive "s/(\[$brackets)','/\1,/g" "$line")" # 1st outer |
|
55 |
debug escaped "$line" |
|
56 |
|
|
57 |
debug expanded |
|
58 |
eval echoEach $line # brace-expand $line |
|
35 | 59 |
done |
Also available in: Unified diff
expand_braces: Also expand XPaths containing [], with up to one level of nesting (which is the most we currently use), because many {} XPaths do in fact contain []. Debug-print intermediate values when env var expand_braces_debug is true. Added usage message.