890 lines
20 KiB
YAML
890 lines
20 KiB
YAML
name: "IFS"
|
|
cases:
|
|
- name: "Default IFS value"
|
|
stdin: |
|
|
# Default IFS is space, tab, newline
|
|
[[ "$IFS" == $' \t\n' ]] && echo "IFS has default value"
|
|
|
|
- name: "Field splitting with default IFS"
|
|
stdin: |
|
|
var="one two three
|
|
four"
|
|
echo "Fields:" $var
|
|
|
|
- name: "Field splitting with custom single-char IFS"
|
|
stdin: |
|
|
IFS=':'
|
|
var="one:two:three"
|
|
echo $var
|
|
|
|
- name: "Field splitting with multi-char IFS"
|
|
stdin: |
|
|
IFS=':,'
|
|
var="one:two,three:four"
|
|
echo $var
|
|
|
|
- name: "Empty IFS disables field splitting"
|
|
stdin: |
|
|
IFS=''
|
|
var="one two three"
|
|
echo "[$var]"
|
|
# Should print with all whitespace preserved
|
|
|
|
- name: "Empty IFS with expansion"
|
|
stdin: |
|
|
IFS=''
|
|
var="a b c"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "[$1]"
|
|
|
|
- name: "Unset IFS uses default splitting"
|
|
stdin: |
|
|
unset IFS
|
|
var="one two three"
|
|
echo $var
|
|
|
|
- name: "IFS whitespace vs non-whitespace splitting"
|
|
stdin: |
|
|
# Non-whitespace IFS chars create empty fields
|
|
IFS=':'
|
|
var=":one::two:"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "Args: $@"
|
|
|
|
- name: "IFS whitespace splitting ignores leading/trailing"
|
|
stdin: |
|
|
# Whitespace IFS chars ignore leading/trailing
|
|
IFS=' '
|
|
var=" one two "
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "Args: $@"
|
|
|
|
- name: "Mixed whitespace and non-whitespace IFS"
|
|
stdin: |
|
|
IFS=' :'
|
|
var="one:two three : four"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "Mixed IFS leading non-whitespace"
|
|
stdin: |
|
|
IFS=': '
|
|
var=":one: :two"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "Mixed IFS trailing non-whitespace"
|
|
stdin: |
|
|
IFS=' :'
|
|
var="one :two: "
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "IFS only whitespace multiple chars"
|
|
stdin: |
|
|
IFS=$' \t'
|
|
var=" one two three "
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "Args: $@"
|
|
|
|
- name: "IFS only non-whitespace multiple chars"
|
|
stdin: |
|
|
IFS=':,'
|
|
var=":,one,:,two,:"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "IFS only tab character"
|
|
stdin: |
|
|
IFS=$'\t'
|
|
var=" a b "
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "Args: $@"
|
|
|
|
- name: "IFS only newline character"
|
|
stdin: |
|
|
IFS=$'\n'
|
|
var="
|
|
|
|
a
|
|
|
|
b
|
|
|
|
"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "Args: $@"
|
|
|
|
- name: "IFS affects command substitution"
|
|
stdin: |
|
|
IFS=':'
|
|
result=$(echo "a:b:c")
|
|
# Command substitution itself doesn't split, but expansion does
|
|
set -- $result
|
|
echo "$#"
|
|
echo "$@"
|
|
|
|
- name: "IFS with command substitution multiline"
|
|
stdin: |
|
|
IFS=$'\n'
|
|
result=$(printf "a\nb\nc")
|
|
set -- $result
|
|
echo "Count: $#"
|
|
echo "$1|$2|$3"
|
|
|
|
- name: "IFS affects arithmetic expansion"
|
|
stdin: |
|
|
IFS=' '
|
|
# Arithmetic expansion result is splittable
|
|
set -- $((1 + 1)) $((2 + 2))
|
|
echo "Count: $#"
|
|
echo "$@"
|
|
|
|
- name: "IFS in array expansion"
|
|
stdin: |
|
|
arr=(one two three)
|
|
IFS=':'
|
|
echo "${arr[*]}"
|
|
# With $* should join with first char of IFS
|
|
|
|
- name: "IFS with $* vs $@"
|
|
stdin: |
|
|
set -- one two three
|
|
IFS=':'
|
|
echo "$*"
|
|
echo "$@"
|
|
|
|
- name: "IFS with $* unquoted"
|
|
stdin: |
|
|
set -- "a:b" "c:d"
|
|
IFS=':'
|
|
# Unquoted $* joins then splits
|
|
set -- $*
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "IFS null char handling"
|
|
stdin: |
|
|
IFS=':'
|
|
var=""
|
|
set -- $var
|
|
echo "Empty var count: $#"
|
|
|
|
- name: "IFS preservation across commands"
|
|
stdin: |
|
|
IFS=':'
|
|
echo "First: $IFS"
|
|
var="a:b"
|
|
echo $var
|
|
echo "After: $IFS"
|
|
|
|
- name: "IFS in subshell"
|
|
stdin: |
|
|
IFS=':'
|
|
(
|
|
echo "In subshell: [$IFS]"
|
|
var="a:b:c"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
)
|
|
echo "Parent: [$IFS]"
|
|
|
|
- name: "IFS local to command"
|
|
stdin: |
|
|
var="a:b:c"
|
|
IFS=':' echo $var
|
|
# IFS assignment should only affect that command
|
|
echo "After: [$IFS]"
|
|
|
|
- name: "IFS does not affect for loop literal words"
|
|
stdin: |
|
|
IFS=':'
|
|
for word in a:b:c; do
|
|
echo "[$word]"
|
|
done
|
|
|
|
- name: "IFS affects for loop variable expansion"
|
|
stdin: |
|
|
IFS=':'
|
|
var="a:b:c"
|
|
for word in $var; do
|
|
echo "[$word]"
|
|
done
|
|
|
|
- name: "IFS affects for loop command substitution"
|
|
stdin: |
|
|
IFS=':'
|
|
for word in $(echo "x:y:z"); do
|
|
echo "[$word]"
|
|
done
|
|
|
|
- name: "IFS with quoted vs unquoted expansion"
|
|
stdin: |
|
|
IFS=':'
|
|
var="a:b:c"
|
|
echo "Unquoted:" $var
|
|
echo "Quoted: $var"
|
|
|
|
- name: "IFS with partially quoted expansion"
|
|
stdin: |
|
|
IFS=':'
|
|
var="a:b:c"
|
|
set -- "$var":more
|
|
echo "Count: $#"
|
|
echo "$@"
|
|
|
|
- name: "IFS whitespace sequence handling"
|
|
stdin: |
|
|
IFS=' '
|
|
var="a b"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "Args: $@"
|
|
|
|
- name: "IFS non-whitespace sequence handling"
|
|
stdin: |
|
|
IFS=':'
|
|
var="a::::b"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "IFS with parameter expansion"
|
|
stdin: |
|
|
IFS=':'
|
|
var="a:b:c"
|
|
result=${var}
|
|
set -- $result
|
|
echo "$#"
|
|
echo "$@"
|
|
|
|
- name: "IFS with parameter expansion default value"
|
|
stdin: |
|
|
IFS=':'
|
|
set -- ${unset:-a:b:c}
|
|
echo "Count: $#"
|
|
echo "$@"
|
|
|
|
- name: "IFS with parameter expansion empty default"
|
|
stdin: |
|
|
IFS=':'
|
|
set -- ${unset:-}
|
|
echo "Count: $#"
|
|
|
|
- name: "IFS with parameter length"
|
|
stdin: |
|
|
IFS=':'
|
|
var="a:b:c"
|
|
# Length expansion returns a number, not subject to further splitting
|
|
len=${#var}
|
|
set -- $len
|
|
echo "Count: $#"
|
|
echo "[$1]"
|
|
|
|
- name: "IFS with glob pattern literal"
|
|
stdin: |
|
|
IFS=':'
|
|
# Glob patterns as literals shouldn't split
|
|
for word in *.txt:*.sh; do
|
|
echo "[$word]"
|
|
done
|
|
|
|
- name: "IFS newline handling"
|
|
stdin: |
|
|
IFS=$'\n'
|
|
var="a
|
|
b
|
|
c"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "$1|$2|$3"
|
|
|
|
- name: "IFS tab handling"
|
|
stdin: |
|
|
IFS=$'\t'
|
|
var="a b c"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "$1|$2|$3"
|
|
|
|
- name: "IFS with backslash in value"
|
|
stdin: |
|
|
IFS=':'
|
|
var='a\:b:c\:d'
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "IFS first char for joining"
|
|
stdin: |
|
|
set -- a b c
|
|
IFS=':'
|
|
# First char of IFS used for $* joining
|
|
result="$*"
|
|
echo "[$result]"
|
|
|
|
- name: "IFS first char empty IFS"
|
|
stdin: |
|
|
set -- a b c
|
|
IFS=''
|
|
result="$*"
|
|
echo "[$result]"
|
|
|
|
- name: "IFS multiple whitespace at start"
|
|
stdin: |
|
|
IFS=' '
|
|
var=" a b"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "$@"
|
|
|
|
- name: "IFS multiple whitespace at end"
|
|
stdin: |
|
|
IFS=' '
|
|
var="a b "
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "$@"
|
|
|
|
- name: "IFS with read builtin integration"
|
|
stdin: |
|
|
IFS=':'
|
|
echo "a:b:c" | (read x y z; echo "x=[$x] y=[$y] z=[$z]")
|
|
|
|
- name: "IFS whitespace before non-whitespace"
|
|
stdin: |
|
|
IFS=' :'
|
|
var=" :a"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "IFS non-whitespace before whitespace"
|
|
stdin: |
|
|
IFS=': '
|
|
var=": a"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
|
|
- name: "Array star join in scalar assignment honors IFS"
|
|
stdin: |
|
|
arr=(a b c)
|
|
IFS=:
|
|
x=${arr[*]}
|
|
echo "[$x]"
|
|
|
|
- name: "Array at join in scalar assignment uses space"
|
|
stdin: |
|
|
arr=(a b c)
|
|
IFS=:
|
|
y=${arr[@]}
|
|
echo "[$y]"
|
|
|
|
- name: "Export assignment from array star honors IFS"
|
|
stdin: |
|
|
np=(/first/bin /usr/lib/llvm/21/bin /usr/bin)
|
|
IFS=:
|
|
export TESTPATH=${np[*]}
|
|
echo "[$TESTPATH]"
|
|
|
|
- name: "Split on IFS then rejoin via star"
|
|
stdin: |
|
|
p="x:y:z"
|
|
IFS=:
|
|
s=( ${p} )
|
|
out=${s[*]}
|
|
echo "[$out]"
|
|
|
|
- name: "Positional star join in scalar assignment honors IFS"
|
|
stdin: |
|
|
set -- a b c
|
|
IFS=:
|
|
x=$*
|
|
echo "[$x]"
|
|
|
|
- name: "Assign-default array star join honors IFS"
|
|
# `:` + a multi-field `:=` argument triggers a pre-existing, unrelated
|
|
# brush quirk ("command not found: <first field>" on stderr); the stdout
|
|
# is what verifies the IFS join.
|
|
ignore_stderr: true
|
|
stdin: |
|
|
arr=(a b c)
|
|
IFS=:
|
|
unset x
|
|
: ${x:=${arr[*]}}
|
|
echo "[$x]"
|
|
|
|
- name: "Assign-default array at join uses space"
|
|
ignore_stderr: true
|
|
stdin: |
|
|
arr=(a b c)
|
|
IFS=:
|
|
unset y
|
|
: ${y:=${arr[@]}}
|
|
echo "[$y]"
|
|
|
|
- name: "Use-default array star join honors IFS"
|
|
stdin: |
|
|
arr=(a b c)
|
|
IFS=:
|
|
unset z
|
|
echo "[${z:-${arr[*]}}]"
|
|
|
|
- name: "Assign-default positional star join honors IFS"
|
|
ignore_stderr: true
|
|
stdin: |
|
|
set -- a b c
|
|
IFS=:
|
|
unset p
|
|
: ${p:=$*}
|
|
echo "[$p]"
|
|
|
|
- name: "Run of non-whitespace delimiters yields empty fields"
|
|
stdin: |
|
|
IFS=:
|
|
var="a:b:::c"
|
|
set -- $var
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "Leading delimiter yields an empty field, trailing one does not"
|
|
stdin: |
|
|
IFS=:
|
|
for var in ":a" "a:" ":a:" ":" "::"; do
|
|
set -- $var
|
|
echo "$var -> $#"
|
|
for arg in "$@"; do
|
|
echo " [$arg]"
|
|
done
|
|
done
|
|
|
|
- name: "Whitespace around a delimiter belongs to the same run"
|
|
stdin: |
|
|
IFS=': '
|
|
for var in "a : b" "a :: b" "a: :b" " a b "; do
|
|
set -- $var
|
|
echo "$var -> $#"
|
|
for arg in "$@"; do
|
|
echo " [$arg]"
|
|
done
|
|
done
|
|
|
|
- name: "Carriage return, vertical tab and form feed split like whitespace"
|
|
stdin: |
|
|
for c in $'\r' $'\v' $'\f'; do
|
|
IFS="$c"
|
|
var="a${c}b${c}${c}c"
|
|
set -- $var
|
|
echo "count=$#"
|
|
done
|
|
|
|
- name: "A delimiter split across two expansions in one word"
|
|
stdin: |
|
|
IFS=:
|
|
a="1:"
|
|
b=":4"
|
|
set -- $a$b
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
- name: "Each field of an array expansion splits on its own"
|
|
stdin: |
|
|
IFS=:
|
|
arr=("a:b" "c::d")
|
|
set -- ${arr[@]}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do
|
|
echo "[$arg]"
|
|
done
|
|
|
|
# Cases below test IFS behavior with empty/unset IFS across different
|
|
# expansion types: variable, brace, mixed, arithmetic, command substitution.
|
|
|
|
- name: "Empty IFS disables splitting of variable expansion"
|
|
stdin: |
|
|
str="a b c"
|
|
IFS=""
|
|
arr=( $str )
|
|
echo "split: ${#arr[@]} elements"
|
|
|
|
- name: "Unset IFS uses default splitting"
|
|
stdin: |
|
|
str="a b c"
|
|
unset IFS
|
|
arr=( $str )
|
|
echo "split: ${#arr[@]} elements"
|
|
|
|
- name: "Local IFS=: then unset restores default splitting"
|
|
stdin: |
|
|
test_func() {
|
|
local str2="a b c"
|
|
local IFS=:
|
|
unset IFS
|
|
local arr=( $str2 )
|
|
echo "split: ${#arr[@]} elements"
|
|
for (( i=0; i<${#arr[@]}; i++ )); do
|
|
echo " [$i]='${arr[$i]}'"
|
|
done
|
|
}
|
|
test_func
|
|
|
|
- name: "Local IFS='' disables splitting of variable"
|
|
stdin: |
|
|
test_func() {
|
|
local str2="a b c"
|
|
local IFS=""
|
|
local arr=( $str2 )
|
|
echo "split: ${#arr[@]} elements"
|
|
for (( i=0; i<${#arr[@]}; i++ )); do
|
|
echo " [$i]='${arr[$i]}'"
|
|
done
|
|
}
|
|
test_func
|
|
|
|
- name: "Brace expansion with local IFS=: then unset"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=:
|
|
unset IFS
|
|
set -- python3_{11..14}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Brace expansion with local IFS=''"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- python3_{11..14}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Mixed variable and brace expansion with local IFS=''"
|
|
stdin: |
|
|
test_func() {
|
|
local str="python3_"
|
|
local IFS=""
|
|
set -- ${str}{11..14}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Command substitution with local IFS=''"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- $(echo "a b c")
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Arithmetic expansion with local IFS=''"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- $((1+1)) $((2+2))
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Special parameters with local IFS=''"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- $*
|
|
echo "Count: $#"
|
|
}
|
|
test_func
|
|
|
|
- name: "Complex mixed variable and brace expansion with local IFS=''"
|
|
stdin: |
|
|
test_func() {
|
|
local str="file"
|
|
local IFS=""
|
|
set -- ${str}{1..3}.txt
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Empty IFS with set -- variable splitting"
|
|
stdin: |
|
|
test_func() {
|
|
local var="a b c"
|
|
local IFS=""
|
|
set -- $var
|
|
echo "Count: $#"
|
|
echo "[$1]"
|
|
}
|
|
test_func
|
|
|
|
- name: "Empty IFS with for-loop variable splitting"
|
|
stdin: |
|
|
test_func() {
|
|
local var="x y z"
|
|
local IFS=""
|
|
for word in $var; do
|
|
echo "[$word]"
|
|
done
|
|
}
|
|
test_func
|
|
|
|
- name: "Empty IFS with comma brace expansion"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- {a,b,c}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Empty IFS with sequence brace expansion"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- {1..5}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Empty IFS with parameter default value expansion"
|
|
stdin: |
|
|
test_func() {
|
|
local var="a b c"
|
|
local IFS=""
|
|
set -- ${var:-default}
|
|
echo "Count: $#"
|
|
echo "[$1]"
|
|
}
|
|
test_func
|
|
|
|
- name: "Empty IFS scoping across nested functions"
|
|
stdin: |
|
|
inner() {
|
|
local IFS=""
|
|
local var="a b c"
|
|
set -- $var
|
|
echo "Inner count: $#"
|
|
}
|
|
outer() {
|
|
local var="a b c"
|
|
set -- $var
|
|
echo "Outer before count: $#"
|
|
inner
|
|
set -- $var
|
|
echo "Outer after count: $#"
|
|
}
|
|
outer
|
|
|
|
- name: "Empty IFS with positional parameters expansion"
|
|
stdin: |
|
|
test_func() {
|
|
local IFS=""
|
|
set -- a b c
|
|
set -- $@
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
}
|
|
test_func
|
|
|
|
- name: "Brace expansion preserves array[@] element separation"
|
|
stdin: |
|
|
arr=(1 2 3)
|
|
set -- {a,b}"${arr[@]}"
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Brace expansion with array[*] concatenates elements"
|
|
stdin: |
|
|
arr=(1 2 3)
|
|
set -- {a,b}"${arr[*]}"
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Brace expansion with unquoted array[@] splits elements"
|
|
stdin: |
|
|
arr=(1 2 3)
|
|
set -- {a,b}${arr[@]}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
|
|
# Brace expansion happens before field splitting and its results are separate
|
|
# words regardless of IFS; a non-whitespace IFS that stays set must not
|
|
# merge or re-split them.
|
|
|
|
- name: "Brace expansion stays separate under IFS=:"
|
|
stdin: |
|
|
IFS=:
|
|
set -- python3_{11..14}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Brace expansion stays separate under IFS=, (the list separator)"
|
|
stdin: |
|
|
IFS=,
|
|
set -- {a,b}{c,d}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Brace expansion under IFS=: still splits the expansions inside it"
|
|
stdin: |
|
|
IFS=:
|
|
v="1:2"
|
|
set -- {$v,x}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Brace expansion under IFS=: with quoted array[*] inside the list"
|
|
stdin: |
|
|
IFS=:
|
|
arr=(1 2)
|
|
set -- {"${arr[*]}",z}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Brace expansion under IFS=: with tilde prefix"
|
|
env:
|
|
HOME: /h
|
|
stdin: |
|
|
IFS=:
|
|
set -- ~/{x,y}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
# `$*` and `${arr[*]}` join with the first character of IFS. An unset IFS
|
|
# means a space; an empty IFS means no separator at all.
|
|
|
|
- name: "Empty IFS joins \"$*\" with no separator"
|
|
stdin: |
|
|
set -- a b c
|
|
IFS=
|
|
echo "[$*]"
|
|
x="$*"
|
|
echo "[$x]"
|
|
arr=(1 2 3)
|
|
echo "[${arr[*]}]"
|
|
y=${arr[*]}
|
|
echo "[$y]"
|
|
|
|
- name: "Unset IFS joins \"$*\" with a space"
|
|
stdin: |
|
|
set -- a b c
|
|
unset IFS
|
|
echo "[$*]"
|
|
arr=(1 2 3)
|
|
echo "[${arr[*]}]"
|
|
|
|
- name: "Empty IFS join inside a larger double-quoted word"
|
|
stdin: |
|
|
set -- a b c
|
|
IFS=
|
|
echo "[<$*>]"
|
|
echo "[${#*}]"
|
|
case "$*" in abc) echo joined;; *) echo "not joined";; esac
|
|
|
|
# Field splitting applies only to the results of parameter expansion, command
|
|
# substitution and arithmetic expansion. Literal text in the word is never
|
|
# split, even when it contains IFS characters, but it is still globbed.
|
|
|
|
- name: "Literal word text is not field-split"
|
|
stdin: |
|
|
IFS=:
|
|
set -- a:b
|
|
echo "Count: $#"
|
|
set -- {a:b,c}
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
set -- a:$'b'
|
|
echo "Count: $#"
|
|
|
|
- name: "Literal word text still globs under a non-default IFS"
|
|
test_files:
|
|
- path: "a:1"
|
|
- path: "a:2"
|
|
stdin: |
|
|
IFS=:
|
|
set -- a:*
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
IFS='*'
|
|
set -- a:*
|
|
echo "Count: $#"
|
|
|
|
- name: "Expansion result adjacent to literal text"
|
|
stdin: |
|
|
IFS=:
|
|
x="1:2"
|
|
set -- $x:3
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
x="1:"
|
|
set -- $x:3
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
set -- pre:$x
|
|
echo "Count: $#"
|
|
for arg in "$@"; do echo "[$arg]"; done
|
|
|
|
- name: "Default and alternate value words are split like any expansion result"
|
|
stdin: |
|
|
IFS=:
|
|
x=
|
|
set -- ${x:-a:b}
|
|
echo "Count: $#"
|
|
set -- ${x:-"a:b"}
|
|
echo "Count: $#"
|
|
set -- ${x:=c:d}
|
|
echo "Count: $#"
|
|
echo "[$x]"
|
|
set -- ${x:+e:f}
|
|
echo "Count: $#"
|
|
|
|
- name: "compgen -W splits its word list on IFS"
|
|
stdin: |
|
|
IFS=:
|
|
compgen -W 'a:b c'
|
|
v="p:q"
|
|
compgen -W "$v"
|