hush: add support for ${var/pattern/repl}, conditional on bash compat

function                                             old     new   delta
expand_vars_to_list                                 2386    2833    +447
expand_string_to_string                               69     110     +41
parse_dollar                                         681     721     +40
hush_main                                            963     945     -18
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/1 up/down: 528/-18)           Total: 510 bytes

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
Denys Vlasenko
2010-09-05 14:45:38 +02:00
parent 701e127f7d
commit 36f774a0cd
12 changed files with 362 additions and 36 deletions

View File

@@ -0,0 +1,14 @@
f
bcdef
abcdef
abcdef
bcde
abcd
abcd
abcdef
bcdef
abcdef
abcdef
abcdef

View File

@@ -0,0 +1,18 @@
var=abcdef
echo ${var:7}
echo ${var:6}
echo ${var:5}
echo ${var:1}
echo ${var:0}
echo ${var:-1}
echo ${var:1:4}
echo ${var:0:4}
echo ${var::4}
echo ${var:-1:4}
echo ${var:1:7}
echo ${var:0:7}
echo ${var::7}
echo ${var:-1:7}

View File

@@ -0,0 +1,10 @@
abc123xcba123
abx123dcba123
abx123dxba123
abcx23dcba123
abcxxxdcbaxxx
abx
xba123
abx23
abc23dcba123
abcdcba

View File

@@ -0,0 +1,24 @@
var=abc123dcba123
echo ${var/d/x}
echo ${var/c/x}
echo ${var//c/x}
echo ${var/[123]/x}
echo ${var//[123]/x}
echo ${var/c*/x}
echo ${var/*c/x}
# must match longest match: result is "abx23"
echo ${var/c*1/x}
# empty replacement - 2nd slash can be omitted
echo ${var/[123]}
echo ${var//[123]}
### ash doesn't support
### # match only at the beginning:
### echo ${var/#a/x}
### echo ${var/#b/x} # should not match
### echo ${var//#b/x} # should not match
### # match only at the end:
### echo ${var/%3/x}

View File

@@ -0,0 +1,20 @@
1 a041#c
2 a041#c
3 a\041#c
4 a\041#c
5 a\041#c
6 a\041#c
7 a\041#c
8 a\041#c
9 a\041#c
10 a\c
11 a\c
12 a\c
13 a\\c
14 a\\c
15 a\\c
16 a\tc
17 a\tc
18 a\tc
19 atc
20 a\tc

View File

@@ -0,0 +1,41 @@
a='abc'
r=${a//b/\041#}
echo 1 $r
echo 2 ${a//b/\041#}
echo 3 "${a//b/\041#}"
a='abc'
r=${a//b/\\041#}
echo 4 $r
echo 5 ${a//b/\\041#}
echo 6 "${a//b/\\041#}"
a='abc'
b='\041#'
r=${a//b/$b}
echo 7 $r
echo 8 ${a//b/$b}
echo 9 "${a//b/$b}"
a='abc'
b='\'
r="${a//b/$b}"
echo 10 $r
echo 11 ${a//b/$b}
echo 12 "${a//b/$b}"
a='abc'
b='\\'
r="${a//b/$b}"
echo 13 $r
echo 14 ${a//b/$b}
echo 15 "${a//b/$b}"
a='abc'
b='\t'
r="${a//b/$b}"
echo 16 $r
echo 17 ${a//b/$b}
echo 18 "${a//b/$b}"
echo 19 ${a//b/\t}
echo 20 "${a//b/\t}"

View File

@@ -0,0 +1,23 @@
Source: a*b\*c
Replace str: _\\_\z_
Pattern: single backslash and star: "replace literal star"
In assignment: a_\_z_b\*c
Unquoted: a_\_z_b\*c
Quoted: a_\_\z_b\*c
Pattern: double backslash and star: "replace backslash and everything after it"
In assignment: a*b_\_z_
Unquoted: a*b_\_z_
Quoted: a*b_\_\z_
Source: a\bc
Replace str: _\\_\z_
Pattern: single backslash and b: "replace b"
In assignment: a\_\_z_c
Unquoted: a\_\_z_c
Quoted: a\_\_\z_c
Pattern: double backslash and b: "replace backslash and b"
In assignment: a_\_z_c
Unquoted: a_\_z_c
Quoted: a_\_\z_c
Done: 0

View File

@@ -0,0 +1,47 @@
# This testcase demonstrates that backslashes are treated differently
# in 1st and 2nd parts of ${var/search/repl}:
# if quoted ("${var/search/repl}"), and repl contains \a (a non-special char),
# the backslash in repl stays; if unquoted, backslash is removed.
# But search part does not act like that: \a is always converted to just a,
# even in quotes.
#
# bash4 (and probably bash3 too): "Quoted:" results are different from
# unquoted and assignment expansions - they have a backslash before z.
v='a*b\*c'
echo 'Source: ' "$v"
echo 'Replace str: ' '_\\_\z_'
echo 'Pattern: ' 'single backslash and star: "replace literal star"'
r=${v/\*/_\\_\z_}
echo 'In assignment:' "$r"
echo 'Unquoted: ' ${v/\*/_\\_\z_}
echo 'Quoted: ' "${v/\*/_\\_\z_}"
echo 'Pattern: ' 'double backslash and star: "replace backslash and everything after it"'
r=${v/\\*/_\\_\z_}
echo 'In assignment:' "$r"
echo 'Unquoted: ' ${v/\\*/_\\_\z_}
echo 'Quoted: ' "${v/\\*/_\\_\z_}"
echo
v='a\bc'
echo 'Source: ' "$v"
echo 'Replace str: ' '_\\_\z_'
echo 'Pattern: ' 'single backslash and b: "replace b"'
r=${v/\b/_\\_\z_}
echo 'In assignment:' "$r"
echo 'Unquoted: ' ${v/\b/_\\_\z_}
echo 'Quoted: ' "${v/\b/_\\_\z_}"
echo 'Pattern: ' 'double backslash and b: "replace backslash and b"'
r=${v/\\b/_\\_\z_}
echo 'In assignment:' "$r"
echo 'Unquoted: ' ${v/\\b/_\\_\z_}
echo 'Quoted: ' "${v/\\b/_\\_\z_}"
echo
echo Done: $?

View File

@@ -0,0 +1,4 @@
a/
a/d
a/e/f
Done: 0

View File

@@ -0,0 +1,11 @@
# This testcase checks whether slashes in ${v/a/b} are parsed before
# or after expansions
v='a/b/c'
s='b/c'
r='e/f'
echo "${v/$s}"
echo "${v/$s/d}"
echo "${v/$s/$r}"
echo Done: $?