Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active December 8, 2024 22:12
Show Gist options
  • Save x-yuri/6c6b375e7b0721a323960baaedf2a649 to your computer and use it in GitHub Desktop.
Save x-yuri/6c6b375e7b0721a323960baaedf2a649 to your computer and use it in GitHub Desktop.
bash: word splitting

bash: word splitting

Word Splitting
IFS=, read -ra fields <<< "$csv_line"

a.bats:

setup() {
    [ "$BATS_LIB_PATH" = /usr/lib/bats ] && BATS_LIB_PATH=~/.bats/lib:$BATS_LIB_PATH
    bats_load_library bats-support
    bats_load_library bats-assert
}

function args2str { local IFS=\|; echo "$#:($*)"; }

# whitespaces are ' ', \t, \n
# IFS whitespaces are whitespaces that are part of IFS

@test 'sequences of IFS whitespaces are stripped at the beginning/end of a word' {
                a=$' \t\na \t\n';  assert_equal  "`args2str $a`"  '1:(a)'
    IFS=$' \t'  a=$' \ta \t';      assert_equal  "`args2str $a`"  '1:(a)'
}

@test 'words are split at sequences of IFS whitespaces' {
                a=$'a \t\nb';  assert_equal  "`args2str $a`"     '2:(a|b)'
                a=$' \t\nb';   assert_equal  "`args2str a$a`"    '2:(a|b)'
                a=$'a \t\n';   assert_equal  "`args2str ${a}b`"  '2:(a|b)'
    IFS=$' \t'  a=$'a \tb';    assert_equal  "`args2str $a`"     '2:(a|b)'
    IFS=$' \t'  a=$' \tb';     assert_equal  "`args2str a$a`"    '2:(a|b)'
    IFS=$' \t'  a=$'a \t';     assert_equal  "`args2str ${a}b`"  '2:(a|b)'
}

@test 'words are split at sequences of IFS non-whitespaces along with adjacent IFS whitespaces' {
    IFS=$' \tx'  a=$'a \tx \tb';  assert_equal  "`args2str $a`"     '2:(a|b)'
    IFS=$' \tx'  a=$' \tx \tb';   assert_equal  "`args2str a$a`"    '2:(a|b)'
    IFS=$' \tx'  a=$'a \tx \t';   assert_equal  "`args2str ${a}b`"  '2:(a|b)'
}

@test 'delimiters are in fact terminators' {
    IFS=x  a=ax;  assert_equal  "`args2str $a`"  '1:(a)'
}

@test 'no word splitting is performed if IFS=' {
    IFS=  a=$' \t\n';  assert_equal  "`args2str $a`"  $'1:( \t\n)'
}

@test 'a word that expands to an empty string, but at least part of it is quoted, produces an empty word' {
    assert_equal  "`args2str ''`"  '1:()'
    a=
    assert_equal  "`args2str "$a"`"  '1:()'
    assert_equal  "`args2str $a"$a"`"  '1:()'
}

@test 'a word that expands to an empty string, and no part of it is quoted, produces no words' {
    a=
    assert_equal  "`args2str $a`"  '0:()'
    assert_equal  "`args2str $a$a`"  '0:()'
}
$ docker run --rm -itv "$PWD":/app -w /app alpine:3.21
/app # apk add bash git ncurses
/app # git clone https://github.com/bats-core/bats-core ~/.bats
/app # git clone https://github.com/bats-core/bats-support ~/.bats/lib/bats-support
/app # git clone https://github.com/bats-core/bats-assert ~/.bats/lib/bats-assert
/app # ~/.bats/bin/bats a.bats
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment