Merge nucleic/sleek-thistle-egret-fyej into dev
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
name: "Array expansion"
|
||||
cases:
|
||||
- name: "Array access"
|
||||
stdin: |
|
||||
y=(a b c)
|
||||
|
||||
echo ${y[@]}
|
||||
echo ${y[*]}
|
||||
|
||||
echo "\${y[@]}: ${y[@]}"
|
||||
echo "\${y[*]}: ${y[*]}"
|
||||
|
||||
var1="${y[@]}"
|
||||
echo "var1: ${var1}"
|
||||
echo $var1
|
||||
|
||||
var2=${y[@]}
|
||||
echo "var2: ${var2}"
|
||||
echo $var2
|
||||
|
||||
var3="${y[*]}"
|
||||
echo "var3: ${var3}"
|
||||
echo $var3
|
||||
|
||||
var4=${y[*]}
|
||||
echo "var4: ${var4}"
|
||||
echo $var4
|
||||
|
||||
for f in "${y[@]}"; do
|
||||
echo "quoted-@ => Element: $f"
|
||||
done
|
||||
|
||||
for f in ${y[@]}; do
|
||||
echo "@ => Element: $f"
|
||||
done
|
||||
|
||||
for f in "${y[*]}"; do
|
||||
echo "quoted-* => Element: $f"
|
||||
done
|
||||
|
||||
for f in ${y[*]}; do
|
||||
echo "* => Element: $f"
|
||||
done
|
||||
|
||||
- name: "Empty arrays"
|
||||
stdin: |
|
||||
myarray=()
|
||||
|
||||
for f in "${myarray[@]}"; do
|
||||
echo "Quoted at-sign element: |$f|"
|
||||
done
|
||||
|
||||
for f in ${myarray[@]}; do
|
||||
echo "Unquoted at-sign element: |$f|"
|
||||
done
|
||||
|
||||
for f in "${myarray[*]}"; do
|
||||
echo "Quoted at-sign element: |$f|"
|
||||
done
|
||||
|
||||
for f in ${myarray[*]}; do
|
||||
echo "Unquoted at-sign element: |$f|"
|
||||
done
|
||||
|
||||
- name: "Mixing array elements and other words"
|
||||
stdin: |
|
||||
myarray=(a b c)
|
||||
|
||||
for f in "${myarray[@]} d e f"; do
|
||||
echo "ELEMENT: $f"
|
||||
done
|
||||
|
||||
for f in ${myarray[@]} d e f; do
|
||||
echo "ELEMENT: $f"
|
||||
done
|
||||
|
||||
- name: "Passing array elements to func"
|
||||
stdin: |
|
||||
myfunc() {
|
||||
echo "In function"
|
||||
for arg in $@; do
|
||||
echo "ARG: |${arg}|"
|
||||
done
|
||||
}
|
||||
|
||||
arr=(a b c "" "e f")
|
||||
myfunc ${arr[@]}
|
||||
myfunc "${arr[@]}"
|
||||
|
||||
- name: "Array length"
|
||||
stdin: |
|
||||
y=(a b c)
|
||||
echo "len(y) = ${#y}"
|
||||
echo "len(y[*]) = ${#y[*]}"
|
||||
echo "len(y[@]) = ${#y[@]}"
|
||||
|
||||
- name: "Array length: single item"
|
||||
stdin: |
|
||||
z=("something here")
|
||||
echo "len(z) = ${#z}"
|
||||
echo "len(z[*]) = ${#z[*]}"
|
||||
echo "len(z[@]) = ${#z[@]}"
|
||||
|
||||
- name: "Array keys: indexed array"
|
||||
stdin: |
|
||||
arr=("element1" "element2" "element3")
|
||||
echo "@: ${!arr[@]}"
|
||||
echo "*: ${!arr[*]}"
|
||||
|
||||
echo "Dumping [@]"
|
||||
for i in "${!arr[@]}"; do
|
||||
echo "@i: $i"
|
||||
done
|
||||
|
||||
echo "Dumping [*]"
|
||||
for i in "${!arr[*]}"; do
|
||||
echo "*i: $i"
|
||||
done
|
||||
|
||||
- name: "Array keys: empty array"
|
||||
stdin: |
|
||||
arr=()
|
||||
echo "@: ${!arr[@]}"
|
||||
echo "*: ${!arr[*]}"
|
||||
|
||||
echo "Dumping [@]"
|
||||
for i in "${!arr[@]}"; do
|
||||
echo "@i: $i"
|
||||
done
|
||||
|
||||
echo "Dumping [*]"
|
||||
for i in "${!arr[*]}"; do
|
||||
echo "*i: $i"
|
||||
done
|
||||
@@ -0,0 +1,145 @@
|
||||
name: "Brace expansion"
|
||||
cases:
|
||||
- name: "Expansion with curly braces: commas"
|
||||
stdin: |
|
||||
echo "{a,b} =>"
|
||||
echo {a,b}
|
||||
echo
|
||||
|
||||
echo "{a} =>"
|
||||
echo {a}
|
||||
echo
|
||||
|
||||
echo "{a} =>"
|
||||
echo {a}
|
||||
echo
|
||||
|
||||
echo "a{,}b =>"
|
||||
echo a{,}b
|
||||
echo
|
||||
|
||||
echo "{} =>"
|
||||
echo {}
|
||||
echo
|
||||
|
||||
echo "1{a,b}2 =>"
|
||||
echo 1{a,b}2
|
||||
echo
|
||||
|
||||
echo "1{a,b}2{c,d}3 =>"
|
||||
echo 1{a,b}2{c,d}3
|
||||
echo
|
||||
|
||||
echo "{a,b}{1,2} =>"
|
||||
echo {a,b}{1,2}
|
||||
echo
|
||||
|
||||
echo 'W\{1,2}X =>'
|
||||
echo W\{1,2}X
|
||||
echo
|
||||
|
||||
echo 'W{1,2\}X =>'
|
||||
echo W{1,2\}X
|
||||
echo
|
||||
|
||||
echo '"W{1,2}X" =>'
|
||||
echo "W{1,2}X"
|
||||
echo
|
||||
|
||||
var=value
|
||||
bar=other
|
||||
echo '{$var,$ba}r =>'
|
||||
echo {$va,$ba}r
|
||||
echo
|
||||
|
||||
echo '\${a,b} =>'
|
||||
echo \${a,b}
|
||||
echo
|
||||
|
||||
- name: "Expansion with curly braces: alpha ranges"
|
||||
stdin: |
|
||||
echo "{a..f} =>"
|
||||
echo {a..f}
|
||||
echo
|
||||
|
||||
echo "{a..f..2} =>"
|
||||
echo {a..f..2}
|
||||
echo
|
||||
|
||||
echo "{a..f..0} =>"
|
||||
echo {a..f..0}
|
||||
echo
|
||||
|
||||
echo "{m..f} =>"
|
||||
echo {m..f}
|
||||
echo
|
||||
|
||||
- name: "Expansion with curly braces: numeric ranges"
|
||||
stdin: |
|
||||
echo "{2..9} =>"
|
||||
echo {2..9}
|
||||
echo
|
||||
|
||||
echo "{+2..+9} =>"
|
||||
echo {+2..+9}
|
||||
echo
|
||||
|
||||
echo "{2..2} =>"
|
||||
echo {2..2}
|
||||
echo
|
||||
|
||||
echo "{2..1} =>"
|
||||
echo {2..1}
|
||||
echo
|
||||
|
||||
echo "{10..2..0} =>"
|
||||
echo {10..2..0}
|
||||
echo
|
||||
|
||||
echo "{10..2..2} =>"
|
||||
echo {10..2..2}
|
||||
echo
|
||||
|
||||
echo "{10..2..-2} =>"
|
||||
echo {10..2..-2}
|
||||
echo
|
||||
|
||||
echo "{2..9..2} =>"
|
||||
echo {2..9..2}
|
||||
echo
|
||||
|
||||
echo "{2..9..0} =>"
|
||||
echo {2..9..0}
|
||||
echo
|
||||
|
||||
echo "{-1..-10} =>"
|
||||
echo {-1..-10}
|
||||
echo
|
||||
|
||||
echo "{-10..-1} =>"
|
||||
echo {-10..-1}
|
||||
echo
|
||||
|
||||
echo "{-1..-10..2} =>"
|
||||
echo {-1..-10..2}
|
||||
echo
|
||||
|
||||
- name: "Expansion with curly braces: nested"
|
||||
stdin: |
|
||||
echo "W{{1..3},a,x}Y =>"
|
||||
echo W{{1..3},a,x}Y
|
||||
echo
|
||||
|
||||
- name: "Iterate through modified array"
|
||||
stdin: |
|
||||
array=("aa" "ba" "ca")
|
||||
|
||||
echo "With quotes:"
|
||||
for i in "${array[@]%a}"; do
|
||||
echo "Element: '$i'"
|
||||
done
|
||||
|
||||
echo "Without quotes:"
|
||||
for i in ${array[@]%a}; do
|
||||
echo "Element: '$i'"
|
||||
done
|
||||
@@ -0,0 +1,222 @@
|
||||
name: "Command substitution"
|
||||
cases:
|
||||
- name: "Command substitution"
|
||||
stdin: |
|
||||
var="value"
|
||||
|
||||
echo "1:"
|
||||
echo $(echo hi)
|
||||
echo "2:"
|
||||
echo "$(echo hi)"
|
||||
echo "3:"
|
||||
echo "$(echo "hi")"
|
||||
echo "4:"
|
||||
echo "$(var="updated"; echo ${var})"
|
||||
echo "var=${var}"
|
||||
|
||||
- name: "Command substitution with embedded parens"
|
||||
stdin: |
|
||||
x=$(echo foo | (wc -l; echo hi))
|
||||
echo "\$x: $x"
|
||||
|
||||
- name: "Command substitution with subshell"
|
||||
stdin: |
|
||||
x=$( (echo hi) )
|
||||
echo "\$x: $x"
|
||||
|
||||
- name: "Command substitution exit code"
|
||||
stdin: |
|
||||
x=$(false) && echo "1. Made it past false"
|
||||
y=$(true) && echo "2. Made it past true"
|
||||
|
||||
- name: "Command substitution with exec"
|
||||
stdin: |
|
||||
x=$(exec echo hi)
|
||||
echo "x: $x"
|
||||
|
||||
- name: "Backtick command substitution"
|
||||
stdin: |
|
||||
echo `echo hi`
|
||||
|
||||
- name: "Backtick command substitution with escaping"
|
||||
stdin: |
|
||||
echo `echo \`echo hi\``
|
||||
|
||||
- name: "Backtick command substitution with backslashes"
|
||||
stdin: |
|
||||
echo `echo \\`
|
||||
|
||||
- name: "Backtick command substitution in double quotes"
|
||||
stdin: |
|
||||
echo "`echo First line`"
|
||||
echo " `echo Second line` "
|
||||
echo "Third`echo line`here"
|
||||
|
||||
- name: "Ignore single quote in comment in command substitution"
|
||||
stdin: |
|
||||
var=$(
|
||||
# I'm
|
||||
echo "Batman"
|
||||
)
|
||||
echo $var
|
||||
|
||||
- name: "Ignore double quote in comment in command substitution"
|
||||
stdin: |
|
||||
var=$(
|
||||
# This " is not being
|
||||
echo "parsed"
|
||||
)
|
||||
echo $var
|
||||
|
||||
- name: "Ignore parentheses in comment in command substitution"
|
||||
stdin: |
|
||||
var=$(
|
||||
# :(
|
||||
echo "Sad"
|
||||
)
|
||||
echo $var
|
||||
|
||||
- name: "Ignore dollar in comment in command substitution"
|
||||
stdin: |
|
||||
var=$(
|
||||
# $
|
||||
echo "Mr. Crabs ^"
|
||||
)
|
||||
echo $var
|
||||
|
||||
- name: "Positional parameter count not mistaken for comment"
|
||||
stdin: |
|
||||
echo $(echo $#)
|
||||
|
||||
- name: "Ignore single quote in comment in command substitution (backticks)"
|
||||
stdin: |
|
||||
var=`
|
||||
# I'm
|
||||
echo "Batman"
|
||||
`
|
||||
echo $var
|
||||
|
||||
- name: "Ignore double quote in comment in command substitution (backticks)"
|
||||
stdin: |
|
||||
var=`
|
||||
# This " is not being
|
||||
echo "parsed"
|
||||
`
|
||||
echo $var
|
||||
|
||||
- name: "Ignore parentheses in comment in command substitution (backticks)"
|
||||
stdin: |
|
||||
var=`
|
||||
# :(
|
||||
echo "Sad"
|
||||
`
|
||||
echo $var
|
||||
|
||||
- name: "Ignore dollar in comment in command substitution (backticks)"
|
||||
stdin: |
|
||||
var=`
|
||||
# $
|
||||
echo "Mr. Crabs ^"
|
||||
`
|
||||
echo $var
|
||||
|
||||
- name: "Positional parameter count not mistaken for comment (backticks)"
|
||||
stdin: |
|
||||
echo `echo $#`
|
||||
|
||||
- name: "Command substitution with only input redir"
|
||||
stdin: |
|
||||
echo "Some text" >file.txt
|
||||
x=$(<file.txt)
|
||||
echo "x: $x"
|
||||
|
||||
- name: "Command substitution with only input redir in pipeline"
|
||||
known_failure: true
|
||||
ignore_stderr: true
|
||||
test_files:
|
||||
- path: file.txt
|
||||
contents: |
|
||||
File Contents
|
||||
stdin: |
|
||||
x=$(<non-existent-file.txt) || x=$(<file.txt)
|
||||
echo "\$?: $?"
|
||||
echo "x: $x"
|
||||
|
||||
- name: "Backquote with only input redir"
|
||||
stdin: |
|
||||
echo "Some text" >file.txt
|
||||
x=`<file.txt`
|
||||
echo "x: $x"
|
||||
|
||||
- name: "Command substitution as simple command preserves exit code"
|
||||
stdin: |
|
||||
$(false)
|
||||
echo "exit code: $?"
|
||||
|
||||
$(true)
|
||||
echo "exit code: $?"
|
||||
|
||||
$(exit 42)
|
||||
echo "exit code: $?"
|
||||
|
||||
- name: "Backtick substitution as simple command preserves exit code"
|
||||
stdin: |
|
||||
`false`
|
||||
echo "exit code: $?"
|
||||
|
||||
`true`
|
||||
echo "exit code: $?"
|
||||
|
||||
- name: "Command substitution with exec as simple command"
|
||||
stdin: |
|
||||
$(exec true)
|
||||
echo "exit code: $?"
|
||||
|
||||
$(exec false)
|
||||
echo "exit code: $?"
|
||||
|
||||
- name: "Command substitution strips null bytes"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
echo "$(echo -e 'a\x00b')" | hexdump -C
|
||||
|
||||
- name: "Backtick substitution strips null bytes"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
echo "`echo -e 'a\x00b'`" | hexdump -C
|
||||
|
||||
- name: "Command substitution strips multiple null bytes"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
echo "$(echo -e 'hello\x00world\x00end')" | hexdump -C
|
||||
|
||||
- name: "Command substitution with only null bytes produces empty string"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
echo "$(echo -e '\x00\x00\x00')" | hexdump -C
|
||||
|
||||
- name: "Variable assignment from command substitution strips null bytes"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
x=$(echo -e 'a\x00b')
|
||||
echo "$x" | hexdump -C
|
||||
|
||||
- name: "Input redirection substitution strips null bytes"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
printf 'a\x00b' > file.txt
|
||||
x=$(<file.txt)
|
||||
echo "$x" | hexdump -C
|
||||
|
||||
- name: "Nested command substitution strips null bytes"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
echo "$(echo "$(echo -e 'a\x00b')")" | hexdump -C
|
||||
|
||||
- name: "Nested command substitution exit code"
|
||||
stdin: |
|
||||
$($(false))
|
||||
echo "exit code: $?"
|
||||
|
||||
$($(:))
|
||||
echo "exit code: $?"
|
||||
@@ -0,0 +1,139 @@
|
||||
name: "Parameter transformation"
|
||||
cases:
|
||||
- name: "Parameter case transformation"
|
||||
stdin: |
|
||||
var="hElLo WoRlD"
|
||||
echo "${var@U}"
|
||||
echo "${var@u}"
|
||||
echo "${var@L}"
|
||||
|
||||
var=("hElLo WoRlD")
|
||||
echo "${var@U}"
|
||||
echo "${var@u}"
|
||||
echo "${var@L}"
|
||||
echo "${var[*]@U}"
|
||||
echo "${var[*]@u}"
|
||||
echo "${var[*]@L}"
|
||||
echo "${var[@]@U}"
|
||||
echo "${var[@]@u}"
|
||||
echo "${var[@]@L}"
|
||||
|
||||
- name: "Parameter quote transformations - Q"
|
||||
stdin: |
|
||||
var='""'
|
||||
echo "\${var@Q}: ${var@Q}"
|
||||
|
||||
var="Hello"
|
||||
echo "\${var@Q}: ${var@Q}"
|
||||
|
||||
var="Hello, world!"
|
||||
echo "\${var@Q}: ${var@Q}"
|
||||
|
||||
var="a 'b c' d"
|
||||
echo "\${var@Q}: ${var@Q}"
|
||||
|
||||
declare -a arr1=(a b c)
|
||||
echo "\${arr1@Q}: ${arr1@Q}"
|
||||
|
||||
declare -A arr2=(["a"]=1 ["b"]=2)
|
||||
echo "\${arr2@Q}: ${arr2@Q}"
|
||||
|
||||
- name: "Parameter quote transformations - K"
|
||||
known_failure: true # TODO(expansion): needs triage and debugging
|
||||
stdin: |
|
||||
var='""'
|
||||
echo "\${var@K}: ${var@K}"
|
||||
|
||||
var="Hello"
|
||||
echo "\${var@K}: ${var@K}"
|
||||
|
||||
var="Hello, world!"
|
||||
echo "\${var@K}: ${var@K}"
|
||||
|
||||
var="a 'b c' d"
|
||||
echo "\${var@K}: ${var@K}"
|
||||
|
||||
declare -a arr1=(a b c)
|
||||
echo "\${arr1@K}: ${arr1@K}"
|
||||
echo "\${arr1[1]@K}: ${arr1[1]@K}"
|
||||
echo "\${arr1[@]@K}: ${arr1[@]@K}"
|
||||
echo "\${arr1[*]@K}: ${arr1[*]@K}"
|
||||
|
||||
declare -A arr2=(["a"]=1 ["b"]=2)
|
||||
echo "\${arr2@K}: ${arr2@K}"
|
||||
echo "\${arr2[b]@K}: ${arr2[b]@K}"
|
||||
echo "\${arr2[@]@K}: ${arr2[@]@K}"
|
||||
echo "\${arr2[*]@K}: ${arr2[*]@K}"
|
||||
|
||||
- name: "Parameter quote transformations - k"
|
||||
min_oracle_version: 5.2
|
||||
stdin: |
|
||||
var='""'
|
||||
echo "\${var@k}: ${var@k}"
|
||||
|
||||
var="Hello"
|
||||
echo "\${var@k}: ${var@k}"
|
||||
|
||||
var="Hello, world!"
|
||||
echo "\${var@k}: ${var@k}"
|
||||
|
||||
declare -a arr1=(a b c)
|
||||
echo "\${arr1@k}: ${arr1@k}"
|
||||
|
||||
declare -A arr2=(["a"]=1 ["b"]=2)
|
||||
echo "\${arr2@k}: ${arr2@k}"
|
||||
|
||||
- name: "Parameter transformations: expand escapes"
|
||||
stdin: |
|
||||
var="a\n\"b"
|
||||
echo "\${var@E}: ${var@E}"
|
||||
|
||||
- name: "Parameter transformation: assignment"
|
||||
stdin: |
|
||||
var="hello"
|
||||
echo "\${var@A}: ${var@A}"
|
||||
|
||||
declare -ia arr=(1 2 3)
|
||||
echo "\${arr@A}: ${arr@A}"
|
||||
echo "\${arr[1]@A}: ${arr[1]@A}"
|
||||
echo "\${arr[@]@A}: ${arr[@]@A}"
|
||||
echo "\${arr[*]@A}: ${arr[*]@A}"
|
||||
|
||||
declare -A arr2=(["a"]=b)
|
||||
echo "\${arr2@A}: ${arr2@A}"
|
||||
echo "\${arr2[@]@A}: ${arr2[@]@A}"
|
||||
echo "\${arr2[*]@A}: ${arr2[*]@A}"
|
||||
|
||||
- name: "Parameter transformation: attributes"
|
||||
stdin: |
|
||||
var="hello"
|
||||
echo "\${var@a}: ${var@a}"
|
||||
|
||||
declare -ia arr=(1 2 3)
|
||||
echo "\${arr@a}: ${arr@a}"
|
||||
|
||||
ref="arr"
|
||||
echo "\${!ref@a}: ${!ref@a}"
|
||||
|
||||
- name: "Parameter transformation @a through nameref"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
declare -i target=42
|
||||
declare -n ref=target
|
||||
echo "ref @a: ${ref@a}"
|
||||
echo "target @a: ${target@a}"
|
||||
|
||||
- name: "Parameter transformation @Q through nameref"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
target="hello world"
|
||||
declare -n ref=target
|
||||
echo "ref @Q: ${ref@Q}"
|
||||
|
||||
- name: "Parameter transformation @A through nameref"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
target="hello"
|
||||
declare -n ref=target
|
||||
echo "ref @A: ${ref@A}"
|
||||
echo "target @A: ${target@A}"
|
||||
@@ -0,0 +1,575 @@
|
||||
name: "Parameter expansion"
|
||||
cases:
|
||||
- name: "String length"
|
||||
stdin: |
|
||||
x="abc"
|
||||
echo "len = ${#x}"
|
||||
|
||||
- name: "Parameter expression: default value"
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# -
|
||||
echo "\${value-default} : ${value-default}"
|
||||
echo "\${empty-default} : ${empty-default}"
|
||||
echo "\${declared-default} : ${declared-default}"
|
||||
echo "\${undeclared-default} : ${undeclared-default}"
|
||||
|
||||
echo "\${value-} : ${value-}"
|
||||
echo "\${empty-} : ${empty-}"
|
||||
echo "\${declared-} : ${declared-}"
|
||||
echo "\${undeclared-} : ${undeclared-}"
|
||||
|
||||
# :-
|
||||
echo "\${value:-default} : ${value:-default}"
|
||||
echo "\${empty:-default} : ${empty:-default}"
|
||||
echo "\${declared:-default} : ${declared:-default}"
|
||||
echo "\${undeclared:-default} : ${undeclared:-default}"
|
||||
|
||||
echo "\${value:-} : ${value:-}"
|
||||
echo "\${empty:-} : ${empty:-}"
|
||||
echo "\${declared:-} : ${declared:-}"
|
||||
echo "\${undeclared:-} : ${undeclared:-}"
|
||||
|
||||
- name: "Parameter expression: assign default value (no colon)"
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# =
|
||||
echo "\${value=default} : ${value=default}"
|
||||
declare -p value
|
||||
echo "\${empty=default} : ${empty=default}"
|
||||
declare -p empty
|
||||
echo "\${declared=default} : ${declared=default}"
|
||||
declare -p declared
|
||||
echo "\${undeclared=default} : ${undeclared=default}"
|
||||
declare -p undeclared
|
||||
|
||||
- name: "Parameter expression: assign default value (no colon, empty replacement)"
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# =
|
||||
echo "\${value=} : ${value=}"
|
||||
declare -p value
|
||||
echo "\${empty=} : ${empty=}"
|
||||
declare -p empty
|
||||
echo "\${declared=} : ${declared=}"
|
||||
declare -p declared
|
||||
echo "\${undeclared=} : ${undeclared=}"
|
||||
declare -p undeclared
|
||||
|
||||
- name: "Parameter expression: assign default value (colon)"
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# :=
|
||||
echo "\${value:=default} : ${value:=default}"
|
||||
declare -p value
|
||||
echo "\${empty:=default} : ${empty:=default}"
|
||||
declare -p empty
|
||||
echo "\${declared:=default} : ${declared:=default}"
|
||||
declare -p declared
|
||||
echo "\${undeclared:=default} : ${undeclared:=default}"
|
||||
declare -p undeclared
|
||||
|
||||
- name: "Parameter expression: assign default value (colon, empty replacement)"
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# :=
|
||||
echo "\${value:=} : ${value:=}"
|
||||
declare -p value
|
||||
echo "\${empty:=} : ${empty:=}"
|
||||
declare -p empty
|
||||
echo "\${declared:=} : ${declared:=}"
|
||||
declare -p declared
|
||||
echo "\${undeclared:=} : ${undeclared:=}"
|
||||
declare -p undeclared
|
||||
|
||||
- name: "Parameter expression: alternative value"
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# +
|
||||
echo "\${value+default} : ${value+default}"
|
||||
echo "\${empty+default} : ${empty+default}"
|
||||
echo "\${declared+default} : ${declared+default}"
|
||||
echo "\${undeclared+default} : ${undeclared+default}"
|
||||
|
||||
echo "\${value+} : ${value+}"
|
||||
echo "\${empty+} : ${empty+}"
|
||||
echo "\${declared+} : ${declared+}"
|
||||
echo "\${undeclared+} : ${undeclared+}"
|
||||
|
||||
# :+
|
||||
echo "\${value:+default} : ${value:+default}"
|
||||
echo "\${empty:+default} : ${empty:+default}"
|
||||
echo "\${declared:+default} : ${declared:+default}"
|
||||
echo "\${undeclared:+default} : ${undeclared:+default}"
|
||||
|
||||
echo "\${value:+} : ${value:+}"
|
||||
echo "\${empty:+} : ${empty:+}"
|
||||
echo "\${declared:+} : ${declared:+}"
|
||||
echo "\${undeclared:+} : ${undeclared:+}"
|
||||
|
||||
- name: "Parameter expression: advanced alternative value"
|
||||
stdin: |
|
||||
value="value"
|
||||
|
||||
echo ${value:+\x}
|
||||
echo ${value:+'x'}
|
||||
echo "${value:+\x}"
|
||||
echo "${value:+'x'}"
|
||||
echo "${value:+x y}"
|
||||
echo "${value:+z 'x' 'y' w}"
|
||||
echo "${value:+x'y'x}"
|
||||
echo "${value:+"x y"}"
|
||||
echo "${value:+"x\xy"}"
|
||||
echo "${value:+z"x\xy"z}"
|
||||
|
||||
- name: "Parameter expression: error on condition (interactive)"
|
||||
ignore_stderr: true
|
||||
args: ["-i"]
|
||||
stdin: |
|
||||
value="value"
|
||||
empty=""
|
||||
declare declared
|
||||
unset undeclared
|
||||
|
||||
# ?
|
||||
echo "\${value?error message} : ${value?error message}"
|
||||
echo " -> result: $?"
|
||||
echo "\${empty?error message} : ${empty?error message}"
|
||||
echo " -> result: $?"
|
||||
echo "\${declared?error message} : ${declared?error message}"
|
||||
echo " -> result: $?"
|
||||
echo "\${undeclared?error message} : ${undeclared?error message}"
|
||||
echo " -> result: $?"
|
||||
|
||||
echo "\${value?} : ${value?}"
|
||||
echo " -> result: $?"
|
||||
echo "\${empty?} : ${empty?}"
|
||||
echo " -> result: $?"
|
||||
echo "\${declared?} : ${declared?}"
|
||||
echo " -> result: $?"
|
||||
echo "\${undeclared?} : ${undeclared?}"
|
||||
echo " -> result: $?"
|
||||
|
||||
# :?
|
||||
echo "\${value:?error message} : ${value:?error message}"
|
||||
echo " -> result: $?"
|
||||
echo "\${empty:?error message} : ${empty:?error message}"
|
||||
echo " -> result: $?"
|
||||
echo "\${declared:?error message} : ${declared:?error message}"
|
||||
echo " -> result: $?"
|
||||
echo "\${undeclared:?error message} : ${undeclared:?error message}"
|
||||
echo " -> result: $?"
|
||||
|
||||
echo "\${value:?} : ${value:?}"
|
||||
echo " -> result: $?"
|
||||
echo "\${empty:?} : ${empty:?}"
|
||||
echo " -> result: $?"
|
||||
echo "\${declared:?} : ${declared:?}"
|
||||
echo " -> result: $?"
|
||||
echo "\${undeclared:?} : ${undeclared:?}"
|
||||
echo " -> result: $?"
|
||||
|
||||
- name: "Parameter expression: error on condition (non-interactive)"
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
echo "${non_existent_var?error message}"
|
||||
echo "This should never execute"
|
||||
|
||||
- name: "Parameter expression: expanded array as alternate value"
|
||||
stdin: |
|
||||
declare -a var=("abc" "def" "ghi" "")
|
||||
|
||||
for item in "${var[@]}"; do
|
||||
echo "Item: '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 1: '${var+"${var[@]}"}'"
|
||||
for item in "${var+"${var[@]}"}"; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 2: '${var+${var[@]}}'"
|
||||
for item in "${var+${var[@]}}"; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 3: '${var+"${var[@]}"}'"
|
||||
for item in ${var+"${var[@]}"}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 4: '${var+${var[@]}}'"
|
||||
for item in ${var+${var[@]}}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 5: '${var+"${var[*]}"}'"
|
||||
for item in "${var+"${var[*]}"}"; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 6: '${var+${var[*]}}'"
|
||||
for item in "${var+${var[*]}}"; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 7: '${var+"${var[*]}"}'"
|
||||
for item in ${var+"${var[*]}"}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 8: '${var+${var[*]}}'"
|
||||
for item in ${var+${var[*]}}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
- name: "Parameter expression: expanded array as default value"
|
||||
stdin: |
|
||||
declare -a var=("abc" "def" "ghi" "")
|
||||
|
||||
for item in "${var[@]}"; do
|
||||
echo "Item: '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 1: ${nonexistent-${var[@]}}"
|
||||
for item in ${nonexistent-${var[@]}}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 2: ${nonexistent-"${var[@]}"}"
|
||||
for item in ${nonexistent-"${var[@]}"}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 3: ${nonexistent2=${var[@]}}"
|
||||
for item in ${nonexistent3=${var[@]}}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
echo "Expression 4: ${nonexistent4="${var[@]}"}"
|
||||
for item in ${nonexistent5-"${var[@]}"}; do
|
||||
echo " -> '${item}'"
|
||||
done
|
||||
|
||||
- name: "Remove prefix/suffix"
|
||||
stdin: |
|
||||
var="prepre-abc-sufsuf"
|
||||
|
||||
# Smallest suffix
|
||||
shopt -u nocasematch
|
||||
echo "\${var%}: ${var%}"
|
||||
echo "\${var%pre}: ${var%pre}"
|
||||
echo "\${var%suf}: ${var%suf}"
|
||||
echo "\${var%SUF}: ${var%SUF}"
|
||||
shopt -s nocasematch
|
||||
echo "\${var%SUF}(nocasematch): ${var%SUF}"
|
||||
|
||||
# Largest suffix
|
||||
shopt -u nocasematch
|
||||
echo "\${var%%}: ${var%%}"
|
||||
echo "\${var%%pre}: ${var%%pre}"
|
||||
echo "\${var%%suf}: ${var%%suf}"
|
||||
echo "\${var%%SUF}: ${var%%SUF}"
|
||||
shopt -s nocasematch
|
||||
echo "\${var%%SUF}(nocasematch): ${var%%SUF}"
|
||||
|
||||
# Smallest prefix
|
||||
shopt -u nocasematch
|
||||
echo "\${var#}: ${var#}"
|
||||
echo "\${var#pre}: ${var#pre}"
|
||||
echo "\${var#suf}: ${var#suf}"
|
||||
echo "\${var#PRE}: ${var#PRE}"
|
||||
shopt -s nocasematch
|
||||
echo "\${var#PRE}(nocasematch): ${var#PRE}"
|
||||
|
||||
# Largest prefix
|
||||
shopt -u nocasematch
|
||||
echo "\${var##}: ${var##}"
|
||||
echo "\${var##pre}: ${var##pre}"
|
||||
echo "\${var##suf}: ${var##suf}"
|
||||
echo "\${var##PRE}: ${var##PRE}"
|
||||
shopt -s nocasematch
|
||||
echo "\${var##PRE}(nocasematch): ${var##PRE}"
|
||||
|
||||
- name: "Indirect variable references"
|
||||
stdin: |
|
||||
var="Hello"
|
||||
ref="var"
|
||||
echo "${!ref}"
|
||||
echo "${!ref//l/o}"
|
||||
|
||||
- name: "Indirect variable references with special parameters"
|
||||
stdin: |
|
||||
set a b c
|
||||
|
||||
ref="2"
|
||||
echo "${!ref}"
|
||||
|
||||
- name: "Indirect variable references with array"
|
||||
stdin: |
|
||||
arr=("element1" "element2" "element3")
|
||||
|
||||
ref="arr[1]"
|
||||
echo "${!ref}"
|
||||
|
||||
ref="arr[10]"
|
||||
echo "${!ref}"
|
||||
|
||||
- name: "Variable prefix match"
|
||||
stdin: |
|
||||
var1="Hello"
|
||||
var2="World"
|
||||
|
||||
echo "${!var*}"
|
||||
echo "${!var@}"
|
||||
|
||||
echo "Dumping *"
|
||||
for i in "${!var*}"; do
|
||||
echo "i: $i"
|
||||
done
|
||||
|
||||
echo "Dumping @"
|
||||
for i in "${!var@}"; do
|
||||
echo "i: $i"
|
||||
done
|
||||
|
||||
- name: "Uppercase first character"
|
||||
stdin: |
|
||||
var="hello"
|
||||
|
||||
shopt -u nocasematch
|
||||
echo "\${var^}: ${var^}"
|
||||
echo "\${var^h}: ${var^h}"
|
||||
echo "\${var^H}: ${var^H}"
|
||||
echo "\${var^l}: ${var^l}"
|
||||
echo "\${var^h*}: ${var^h*}"
|
||||
echo "\${var^he}: ${var^he}"
|
||||
echo "\${var^?}: ${var^?}"
|
||||
echo "\${var^*}: ${var^*}"
|
||||
|
||||
shopt -s nocasematch
|
||||
echo "\${var^H}(nocasematch): ${var^H}"
|
||||
|
||||
arr=("hello" "world")
|
||||
echo "\${arr^}: ${arr^}"
|
||||
echo "\${arr[@]^}: ${arr[@]^}"
|
||||
echo "\${arr[*]^}: ${arr[*]^}"
|
||||
|
||||
- name: "Uppercase matching pattern"
|
||||
stdin: |
|
||||
var="hello"
|
||||
|
||||
shopt -u nocasematch
|
||||
echo "\${var^^}: ${var^^}"
|
||||
echo "\${var^^l}: ${var^^l}"
|
||||
echo "\${var^^L}: ${var^^L}"
|
||||
echo "\${var^^m}: ${var^^m}"
|
||||
|
||||
shopt -s nocasematch
|
||||
echo "\${var^^L}(nocasematch): ${var^^L}"
|
||||
|
||||
arr=("hello" "world")
|
||||
echo "\${arr^^}: ${arr^^}"
|
||||
echo "\${arr[@]^^}: ${arr[@]^^}"
|
||||
echo "\${arr[*]^^}: ${arr[*]^^}"
|
||||
|
||||
- name: "Lowercase first character"
|
||||
stdin: |
|
||||
var="HELLO"
|
||||
|
||||
shopt -u nocasematch
|
||||
echo "\${var,}: ${var,}"
|
||||
echo "\${var,h}: ${var,h}"
|
||||
echo "\${var,H}: ${var,H}"
|
||||
echo "\${var,L}: ${var,L}"
|
||||
echo "\${var,H*}: ${var,H*}"
|
||||
echo "\${var,HE}: ${var,HE}"
|
||||
echo "\${var,?}: ${var,?}"
|
||||
echo "\${var,*}: ${var,*}"
|
||||
|
||||
shopt -s nocasematch
|
||||
echo "\${var,h}(nocasematch): ${var,h}"
|
||||
|
||||
arr=("HELLO" "WORLD")
|
||||
echo "\${arr,}: ${arr,}"
|
||||
echo "\${arr[@],}: ${arr[@],}"
|
||||
echo "\${arr[*],}: ${arr[*],}"
|
||||
|
||||
- name: "Lowercase matching pattern"
|
||||
stdin: |
|
||||
var="HELLO"
|
||||
|
||||
shopt -u nocasematch
|
||||
echo "\${var,,}: ${var,,}"
|
||||
echo "\${var,,M}: ${var,,M}"
|
||||
echo "\${var,,L}: ${var,,L}"
|
||||
echo "\${var,,l}: ${var,,l}"
|
||||
|
||||
shopt -s nocasematch
|
||||
echo "\${var,,l}(nocasematch): ${var,,l}"
|
||||
|
||||
arr=("HELLO" "WORLD")
|
||||
echo "\${arr,,}: ${arr,,}"
|
||||
echo "\${arr[@],,}: ${arr[@],,}"
|
||||
echo "\${arr[*],,}: ${arr[*],,}"
|
||||
|
||||
- name: "Substring replacement"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
echo "\${var/world/WORLD}: ${var/world/WORLD}"
|
||||
|
||||
arr=("world" "world")
|
||||
echo "\${arr/world/WORLD}: ${arr/world/WORLD}"
|
||||
echo "\${arr[@]/world/WORLD}: ${arr[@]/world/WORLD}"
|
||||
echo "\${arr[*]/world/WORLD}: ${arr[*]/world/WORLD}"
|
||||
|
||||
- name: "Substring replacement with slashes"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
echo "\${var/world//world}: ${var/world//world}"
|
||||
|
||||
- name: "Substring replacement with patterns"
|
||||
stdin: |
|
||||
var="a[bc]d"
|
||||
pattern="[bc]"
|
||||
echo "Replacement 1: ${var/${pattern}/}"
|
||||
echo "Replacement 2: ${var/"${pattern}"/}"
|
||||
|
||||
- name: "Prefix substring replacement"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
echo "\${var/#world/WORLD}: ${var/#world/WORLD}"
|
||||
echo "\${var/#Hello/HELLO}: ${var/#Hello/HELLO}"
|
||||
|
||||
arr=("world" "world")
|
||||
echo "\${arr/#world/WORLD}: ${arr/#world/WORLD}"
|
||||
echo "\${arr[@]/#world/WORLD}: ${arr[@]/#world/WORLD}"
|
||||
echo "\${arr[*]/#world/WORLD}: ${arr[*]/#world/WORLD}"
|
||||
|
||||
- name: "Suffix substring replacement"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
echo "\${var/%Hello/HELLO}: ${var/%Hello/HELLO}"
|
||||
echo "\${var/%world!/WORLD!}: ${var/%world!/WORLD!}"
|
||||
|
||||
arr=("world" "world")
|
||||
echo "\${arr/%world/WORLD}: ${arr/%world/WORLD}"
|
||||
echo "\${arr[@]/%world/WORLD}: ${arr[@]/%world/WORLD}"
|
||||
echo "\${arr[*]/%world/WORLD}: ${arr[*]/%world/WORLD}"
|
||||
|
||||
- name: "Global substring replacement"
|
||||
stdin: |
|
||||
var="Hello, world, world!"
|
||||
echo "\${var//world/WORLD}: ${var//world/WORLD}"
|
||||
|
||||
arr=("world world" "world world")
|
||||
echo "\${arr//world/WORLD}: ${arr//world/WORLD}"
|
||||
echo "\${arr[@]//world/WORLD}: ${arr[@]//world/WORLD}"
|
||||
echo "\${arr[*]//world/WORLD}: ${arr[*]//world/WORLD}"
|
||||
|
||||
- name: "Global substring removal"
|
||||
stdin: |
|
||||
var="That is not all"
|
||||
|
||||
shopt -u nocasematch
|
||||
echo "\${var//not }: ${var//not}"
|
||||
|
||||
shopt -s nocasematch
|
||||
echo "\${var//NOT }: ${var//NOT }"
|
||||
|
||||
- name: "Substring from offset"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
echo "\${var:0}: ${var:0}"
|
||||
echo "\${var:7}: ${var:7}"
|
||||
echo "\${var: 7 }: ${var: 7 }"
|
||||
echo "\${var:50}: ${var:50}"
|
||||
echo "\${var:-1}: ${var:-1}"
|
||||
echo "\${var: -1}: ${var: -1}"
|
||||
echo "\${var: 2 + 3 }: ${var: 2 + 3 }"
|
||||
|
||||
- name: "Substring with length"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
echo "\${var:0:1}: ${var:0:1}"
|
||||
echo "\${var:0:0}: ${var:0:0}"
|
||||
echo "\${var:0:50}: ${var:0:50}"
|
||||
echo "\${var:0:-1}: ${var:0:-1}"
|
||||
echo "\${var:0:-3}: ${var:0:-3}"
|
||||
echo "\${var:7:3}: ${var:7:3}"
|
||||
echo "\${var:50:2}: ${var:50:2}"
|
||||
echo "\${var:-1:1}: ${var:-1:1}"
|
||||
echo "\${var:-3:1}: ${var:-3:1}"
|
||||
|
||||
- name: "Substring on string with multi-byte chars"
|
||||
skip: true # TODO(expansion): succeeds on macOS, fails on Linux
|
||||
stdin: |
|
||||
var="7❌🖌️✅😂🔴⛔ABC"
|
||||
echo "${var:2}" | hexdump -C
|
||||
|
||||
- name: "Substring operator on arrays"
|
||||
stdin: |
|
||||
set abcde fghij klmno pqrst uvwxy z
|
||||
echo "\${@:2:2}: ${@:2:2}"
|
||||
echo "\${@:2}: ${@:2}"
|
||||
|
||||
myarray=(abcde fghij klmno pqrst uvwxy z)
|
||||
echo "\${myarray[@]:2:2}: ${myarray[@]:2:2}"
|
||||
echo "\${myarray[@]:2}: ${myarray[@]:2}"
|
||||
|
||||
- name: "Substring operator on arrays with negative index"
|
||||
stdin: |
|
||||
set abcde fghij klmno pqrst uvwxy z
|
||||
echo "\${@: -2:2}: ${@: -2:2}"
|
||||
echo "\${@: -2}: ${@: -2}"
|
||||
|
||||
myarray=(abcde fghij klmno pqrst uvwxy z)
|
||||
echo "\${myarray[@]: -2:2}: ${myarray[@]: -2:2}"
|
||||
echo "\${myarray[@]: -2}: ${myarray[@]: -2}"
|
||||
|
||||
- name: "Substring operator on single-element array"
|
||||
stdin: |
|
||||
myarray=("abcde fghij klmno pqrst uvwxy z")
|
||||
echo "\${myarray[@]:0:1}: ${myarray[@]:0:1}"
|
||||
echo "\${myarray[@]:1}: ${myarray[@]:1}"
|
||||
|
||||
- name: "Substring operator past end of array"
|
||||
stdin: |
|
||||
set a b c
|
||||
declare -a result1=("${@:3}")
|
||||
declare -p result1
|
||||
|
||||
myarray=(a b c)
|
||||
declare -a result2=("${myarray[@]:3}")
|
||||
declare -p result2
|
||||
|
||||
- name: "Substring with length (with nested expressions)"
|
||||
stdin: |
|
||||
var="Hello, world!"
|
||||
offset=7
|
||||
length=5
|
||||
echo "\${var:\$offset:\${length}}: ${var:$offset:${length}}"
|
||||
@@ -0,0 +1,84 @@
|
||||
name: "Quotes"
|
||||
cases:
|
||||
- name: "Single quotes"
|
||||
stdin: |
|
||||
var=xyz
|
||||
echo 'Quoted string'
|
||||
echo 'abc ${var} def'
|
||||
|
||||
- name: "Double quotes"
|
||||
stdin: |
|
||||
echo "\""
|
||||
|
||||
- name: "Double quotes: escaping"
|
||||
stdin: |
|
||||
echo "1. \'" | hexdump -C
|
||||
echo "2. \x" | hexdump -C
|
||||
echo "\n"
|
||||
|
||||
- name: "ANSI-C quotes"
|
||||
stdin: |
|
||||
single_quoted='\n'
|
||||
echo "Single quoted len: ${#single_quoted}"
|
||||
echo -n '\n' | hexdump -C
|
||||
|
||||
ansi_c_quoted=$'\n'
|
||||
echo "ANSI-C quoted len: ${#ansi_c_quoted}"
|
||||
echo -n $'\n' | hexdump -C
|
||||
|
||||
- name: "ANSI-C quotes with escape sequences"
|
||||
stdin: |
|
||||
echo -n "0. "$'\x' | hexdump -C
|
||||
echo -n "1. "$'\x65' | hexdump -C
|
||||
echo -n "2. "$'\xgg' | hexdump -C
|
||||
echo -n "3. "$'\x{65}' | hexdump -C
|
||||
echo -n "4. "$'\x{65' | hexdump -C
|
||||
echo -n "5. "$'\x{65R}' | hexdump -C
|
||||
echo -n "6. "$'\x{}R' | hexdump -C
|
||||
echo -n "7. "$'\x{ }' | hexdump -C
|
||||
echo -n "8. "$'\x{965}' | hexdump -C
|
||||
echo -n "9. "$'\'\"' | hexdump -C
|
||||
echo -n "10. "$'🐢' | hexdump -C
|
||||
echo -n "11. "$'\101' | hexdump -C
|
||||
echo -n "12. "$'\10' | hexdump -C
|
||||
echo -n "13. "$'\1' | hexdump -C
|
||||
echo -n "14. "$'\0' | hexdump -C
|
||||
echo -n "15. "$'\001' | hexdump -C
|
||||
echo -n "16. "$'abc \0 def' | hexdump -C
|
||||
echo -n "17. "$'\ca' | hexdump -C
|
||||
echo -n "18. "$'\cz' | hexdump -C
|
||||
echo -n "19. "$'\cA' | hexdump -C
|
||||
echo -n "20. "$'\cZ' | hexdump -C
|
||||
echo -n "21. "$'\c ' | hexdump -C
|
||||
echo -n "22. "$'\c!' | hexdump -C
|
||||
echo -n "23. "$'\c/' | hexdump -C
|
||||
echo -n "24. "$'\c0' | hexdump -C
|
||||
echo -n "25. "$'\c9' | hexdump -C
|
||||
echo -n "26. "$'\c:' | hexdump -C
|
||||
echo -n "27. "$'\c@' | hexdump -C
|
||||
echo -n "28. "$'\c[' | hexdump -C
|
||||
echo -n "29. "$'\c]' | hexdump -C
|
||||
echo -n "30. "$'\c`' | hexdump -C
|
||||
echo -n "31. "$'\c{' | hexdump -C
|
||||
echo -n "32. "$'\c?' | hexdump -C
|
||||
echo -n "33. "$'\c*' | hexdump -C
|
||||
echo -n "34. "$'\c^' | hexdump -C
|
||||
echo -n "35. "$'\c_' | hexdump -C
|
||||
echo -n "36. "$'\c' | hexdump -C
|
||||
echo -n "37. "$'\c\\' | hexdump -C
|
||||
echo -n "38. "$'\c\n' | hexdump -C
|
||||
echo -n "39. "$'\\' | hexdump -C
|
||||
|
||||
- name: "ANSI-C quote syntax inside double quotes (literal, not processed)"
|
||||
stdin: |
|
||||
# When $'...' appears inside double quotes, it should be treated as literal text
|
||||
echo "$'\t'"
|
||||
echo "$'\'abcd\''"
|
||||
x="$'\n'"
|
||||
echo "len: ${#x}"
|
||||
echo "$x"
|
||||
|
||||
- name: "gettext style quotes"
|
||||
stdin: |
|
||||
quoted=$"Hello, world"
|
||||
echo "Content: [${quoted}]"
|
||||
@@ -0,0 +1,141 @@
|
||||
name: "Tilde expansion"
|
||||
cases:
|
||||
- name: "Tilde expansion: basic"
|
||||
home_dir: .
|
||||
stdin: |
|
||||
test_root=$(realpath $(pwd))
|
||||
|
||||
mkdir subdir
|
||||
cd subdir
|
||||
|
||||
D=~
|
||||
D=$(realpath $D)
|
||||
echo "~: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
- name: "Tilde expansion: explicit user"
|
||||
home_dir: .
|
||||
stdin: |
|
||||
test_root=$(pwd)
|
||||
|
||||
D=~root
|
||||
echo "~root: $D"
|
||||
|
||||
D=~nonexistentuserwhodoesnotexist
|
||||
echo "~<non-existent-username>: $D"
|
||||
|
||||
- name: "Tilde expansion: working dirs"
|
||||
home_dir: .
|
||||
stdin: |
|
||||
test_root=$(pwd)
|
||||
|
||||
mkdir subdir
|
||||
cd subdir
|
||||
|
||||
D=~+
|
||||
echo "~+: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=~-
|
||||
echo "~-: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
unset OLDPWD
|
||||
D=~-
|
||||
echo "~- (without OLDPWD): ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
- name: "Tilde expansion: dir stack"
|
||||
stdin: |
|
||||
test_root=$(pwd)
|
||||
|
||||
for name in a b c d e f g; do
|
||||
mkdir $name
|
||||
pushd $name >/dev/null 2>&1
|
||||
done
|
||||
|
||||
D=~2
|
||||
echo "~2: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=~9
|
||||
echo "~9: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=~+2
|
||||
echo "~+2: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=~+9
|
||||
echo "~+9: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=~-2
|
||||
echo "~-2: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=~-9
|
||||
echo "~-9: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
- name: "Tilde expansion: after colons"
|
||||
home_dir: .
|
||||
stdin: |
|
||||
test_root=~
|
||||
|
||||
D=something:~
|
||||
echo "D: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=something":"~
|
||||
echo "D: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=something:"~"
|
||||
echo "D: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=something:~:another:~
|
||||
echo "D: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
- name: "Tilde expansion: unexpanded tildes"
|
||||
home_dir: .
|
||||
stdin: |
|
||||
test_root=$(pwd)
|
||||
|
||||
D="~"
|
||||
echo "D: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
D=x~
|
||||
echo "D: ${D//${test_root}/TEST_ROOT}"
|
||||
|
||||
- name: "Tilde expansion: colon context sensitivity"
|
||||
env:
|
||||
HOME: /testhome
|
||||
stdin: |
|
||||
# Tilde at word start always expands (in both contexts)
|
||||
echo "echo tilde: $(echo ~)"
|
||||
var=~
|
||||
echo "assignment tilde: ${var}"
|
||||
|
||||
# Tilde after colon: should NOT expand in non-assignment context
|
||||
echo "echo with colon: $(echo ~:~/bin)"
|
||||
echo ~:~/bin
|
||||
|
||||
# But SHOULD expand in assignment context
|
||||
var=~:~/bin
|
||||
echo "assignment with colon: ${var}"
|
||||
|
||||
# Complex PATH-like example
|
||||
PATH=/usr/bin:~:/bin:~/local
|
||||
echo "PATH: ${PATH}"
|
||||
|
||||
- name: "Tilde expansion: parameter defaults"
|
||||
env:
|
||||
HOME: /testhome
|
||||
stdin: |
|
||||
echo "Use default value with tilde"
|
||||
unset myvar
|
||||
echo "Default: ${myvar:-~}"
|
||||
echo "myvar after :-: ${myvar}"
|
||||
|
||||
echo "Assign default value with tilde"
|
||||
unset myvar
|
||||
echo "Assign default: ${myvar:=~}"
|
||||
echo "myvar after :=: ${myvar}"
|
||||
|
||||
echo "Use default with colon-tilde"
|
||||
unset myvar2
|
||||
echo "Default colon-tilde: ${myvar2:-~:~/bin}"
|
||||
|
||||
echo "Assign default with colon-tilde"
|
||||
unset myvar3
|
||||
echo "Assign colon-tilde: ${myvar3:=~:~/bin}"
|
||||
echo "myvar3 after := ${myvar3}"
|
||||
@@ -0,0 +1,77 @@
|
||||
name: "Variable expansion"
|
||||
cases:
|
||||
- name: "Undefined variables"
|
||||
stdin: |
|
||||
echo "Undefined: ${undefined}"
|
||||
echo "Undefined: $undefined"
|
||||
|
||||
- name: "Defined variables"
|
||||
stdin: |
|
||||
var=xyz
|
||||
echo "Defined: ${var}"
|
||||
echo "Defined: var"
|
||||
echo "Defined: prefix${var}suffix"
|
||||
echo "Defined: prefix$var"
|
||||
|
||||
- name: "Undefined positional params"
|
||||
stdin: |
|
||||
echo "Param: $9"
|
||||
echo "Param: ${9}"
|
||||
|
||||
- name: "High-numbered positional params"
|
||||
stdin: |
|
||||
echo "Param: $99"
|
||||
echo "Param: ${99}"
|
||||
|
||||
- name: "Nameref indirect expansion returns target name"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
target="the_value"
|
||||
declare -n ref=target
|
||||
echo "indirect: ${!ref}"
|
||||
echo "direct: $ref"
|
||||
|
||||
- name: "Nameref with string operations"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
target="Hello World"
|
||||
declare -n ref=target
|
||||
echo "upper: ${ref^^}"
|
||||
echo "lower: ${ref,,}"
|
||||
echo "length: ${#ref}"
|
||||
echo "substring: ${ref:0:5}"
|
||||
echo "replace: ${ref/World/Bash}"
|
||||
|
||||
- name: "Nameref with default value expansion"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
declare -n ref=unset_var
|
||||
echo "default: ${ref:-default_value}"
|
||||
echo "assign default: ${ref:=assigned}"
|
||||
echo "unset_var: $unset_var"
|
||||
|
||||
- name: "Nameref with error expansion"
|
||||
known_failure: true
|
||||
ignore_stderr: true
|
||||
stdin: |
|
||||
declare -n ref=unset_var
|
||||
echo "${ref:?should error}" 2>/dev/null || echo "caught error"
|
||||
|
||||
- name: "Nameref with alternative expansion"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
target="exists"
|
||||
declare -n ref=target
|
||||
echo "${ref:+alternative}"
|
||||
unset target
|
||||
echo "'${ref:+alternative}'"
|
||||
|
||||
- name: "Nameref with pattern removal"
|
||||
known_failure: true
|
||||
stdin: |
|
||||
target="/usr/local/bin/bash"
|
||||
declare -n ref=target
|
||||
echo "## */: ${ref##*/}"
|
||||
echo "%% /*: ${ref%%/*}"
|
||||
echo "# */: ${ref#*/}"
|
||||
echo "% /*: ${ref%/*}"
|
||||
Reference in New Issue
Block a user