Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Word splitting in Bash with IFS set to a non-whitespace character

I'm going through a Bash tutorial, and specifically the subject of word splitting.

This script, called "args", helps demonstrate word splitting examples:

#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo

An example:

$ ./args hello world, here is "a string of text!"
5 args: <hello> <world,> <here> <is> <a string of text!>

So far so good. I understand how this works.

However, when I replace IFS with a non-whitespace character, say :, the script does not perform word splitting if I pass the string directly as an argument.

$ ./args one:two:three
1 args: <one:two:three>

However, the script does perform word splitting on the same string if I (1) assign the string to a variable, and then (2) pass the string to the script via parameter expansion.

$ IFS=:
$ variable="one:two:three"
$ ./args $variable
3 args: <one> <two> <three>

Why? Specifically, why does passing the string as an argument undergo word splitting when IFS is unset and the delimiters are whitespace characters, but not when IFS is set to non-whitespace characters?

When I use read instead of this script, the same string also undergoes word splitting as expected.

$ IFS=:
$ read a b c
one:two:three
$ echo $a $b $c
one two three
like image 200
Nadim Hussami Avatar asked Apr 01 '17 23:04

Nadim Hussami


People also ask

How do you split words in bash?

In bash, a string can also be divided without using $IFS variable. The 'readarray' command with -d option is used to split the string data. The -d option is applied to define the separator character in the command like $IFS. Moreover, the bash loop is used to print the string in split form.

Does bash ignore whitespace?

Bash uses whitespace to determine where words begin and end. The first word is the command name and additional words become arguments to that command.

How do I split a string in space bash?

Example-1: Split string based on space The shell variable, $IFS is used to assign the character that will be used for dividing the string data. Space is used in this script as the separator. '-a' option is used with reading command to store the split-ted data into an array variable named $strarr.


1 Answers

You can read more about word splitting here.

The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.

When you pass the bare string one:two:three as an argument with IFS set to :, Bash doesn't do word splitting because the bare string is not one of parameter expansion, command substitution, or arithmetic expansion contexts.

However, when the same string is assigned to a variable and the variable is passed to the script unquoted, word splitting does occur as it is a case of parameter expansion.

The same thing applies to these as well (command substitution):

$ ./args $(echo one:two:three)
3 args: <one> <two> <three>

$ ./args "$(echo one:two:three)"
1 args: <one:two:three>

As documented, read command does do word splitting on every line read, unless IFS has been set to an empty string.


like image 120
codeforester Avatar answered Sep 20 '22 05:09

codeforester