Skip to main content
added 579 characters in body
Source Link
Stéphane Chazelas
  • 584.8k
  • 96
  • 1.1k
  • 1.7k

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh, other shells either remove the NULs or choke on them). Those (not NUL) also happen to be IFS-whitespace charactercharacters¹, which are treated specially when it comes to IFS-splitting.

If the output of cmd is " a b\nc \n", that split+glob operator will generate a "a", "b" and "c" arguments to ./input. With IFS-white-space characters, it's impossible for split+glob to generate an empty argument because sequences of one or more IFS-whitespace characters are treated as one delimiter. To generate an empty argument, you'd need to choose a separator that is not an IFS-whitespace character. Actually, any non-whitespace character but SPC, TAB or NL will do (best to also avoid multi-byte characters which are not supported by all shells here).

Those " are part of the shell syntax, they are shell quoting operators. Those " characters are not passed to input.


¹ IFS whitespace characters, per POSIX being the characters classified as [:space:] in the locale and that happen to be in $IFS though in ksh88 (on which the POSIX specification is based) and in most shells, that's still limited to SPC, TAB and NL. The only POSIX compliant shell in that regard I found was yash. ksh93 and bash (since 5.0) also include other whitespace (such as CR, FF, VT...), but limited to the single-byte ones (beware on some systems like Solaris, that includes the non-breaking-space which is single byte in some locales)

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh, other shells either remove the NULs or choke on them). Those (not NUL) also happen to be IFS-whitespace character, which are treated specially when it comes to IFS-splitting.

If the output of cmd is " a b\nc \n", that split+glob operator will generate a "a", "b" and "c" arguments to ./input. With IFS-white-space characters, it's impossible for split+glob to generate an empty argument because sequences of one or more IFS-whitespace characters are treated as one delimiter. To generate an empty argument, you'd need to choose a separator that is not an IFS-whitespace character. Actually, any character but SPC, TAB or NL will do (best to also avoid multi-byte characters which are not supported by all shells here).

Those " are part of the shell syntax, they are shell quoting operators. Those " characters are not passed to input.

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh, other shells either remove the NULs or choke on them). Those (not NUL) also happen to be IFS-whitespace characters¹, which are treated specially when it comes to IFS-splitting.

If the output of cmd is " a b\nc \n", that split+glob operator will generate a "a", "b" and "c" arguments to ./input. With IFS-white-space characters, it's impossible for split+glob to generate an empty argument because sequences of one or more IFS-whitespace characters are treated as one delimiter. To generate an empty argument, you'd need to choose a separator that is not an IFS-whitespace character. Actually, any non-whitespace character will do (best to also avoid multi-byte characters which are not supported by all shells here).

Those " are part of the shell syntax, they are shell quoting operators. Those " characters are not passed to input.


¹ IFS whitespace characters, per POSIX being the characters classified as [:space:] in the locale and that happen to be in $IFS though in ksh88 (on which the POSIX specification is based) and in most shells, that's still limited to SPC, TAB and NL. The only POSIX compliant shell in that regard I found was yash. ksh93 and bash (since 5.0) also include other whitespace (such as CR, FF, VT...), but limited to the single-byte ones (beware on some systems like Solaris, that includes the non-breaking-space which is single byte in some locales)

added 54 characters in body
Source Link
Stéphane Chazelas
  • 584.8k
  • 96
  • 1.1k
  • 1.7k

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh, other shells either remove the NULs or choke on them). Those (not NUL) also happen to be IFS-whitespace character, which are treated specially when it comes to IFS-splitting.

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh). Those (not NUL) also happen to be IFS-whitespace character, which are treated specially when it comes to IFS-splitting.

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh, other shells either remove the NULs or choke on them). Those (not NUL) also happen to be IFS-whitespace character, which are treated specially when it comes to IFS-splitting.

added 317 characters in body
Source Link
Stéphane Chazelas
  • 584.8k
  • 96
  • 1.1k
  • 1.7k

Because, $(cmd) is unquoted, that's a split+glob operator. The shell retrieves the output of cmd, removes all the trailing newline characters, then splits that based on the value of the $IFS special characterparameter, and then performs file namefilename generation (for instance turns *.txt tointo the list of non-hidden txt files in the current directory) on the resultresulting words (that latter part not with zsh) and in the case of ksh also performs brace expansion (turns a{b,c} into ab and ac for instance).

The default value of $IFS contains the SPC, TAB and NL charactercharacters (also NUL in zsh). Those (not NUL) also happen to be IFS-white-spacewhitespace character, which are treated specially when it comes to IFS-splitting.

If the output of cmd is " a b\nc \n", that split+glob operator will generate a "a", "b" and "c" arguments to ./input. With IFS-white-space characters, it's impossible for split+glob to generate an empty argument because sequences of one or more IFS-whitespace characters are treated as one delimiter. To generate an empty argument, you'd need to choose a separator that is not an IFS-whitespace character. Actually, any character but SPC, TAB or NL will do (best to also avoid multi-byte characters which are not supported by all shells here).

IFS=:          # split on ":" which is not an IFS-whitespace character
set -o noglob  # disable globbing (also brace expansion in ksh)
./input $(cmd)

And if cmd outputs a::b\n, then that split+glob operator will result in a "a", "" and "b" arguments (note that the "s are not part of the value, I'm just using them here to help show the values).

With a:b:\n, depending on the shell, that will result in "a" and "b" or "a", "b" and "". You can make it consistent across all shells with

./input $(cmd)""

(which also means that for an empty output of cmd (or an output consisting only of newline characters), ./input will receive one empty argument as opposed to no argument at all).

cmd() {
  printf 'a b::b\n' c\n'
}
input() {
  printf 'I got %d arguments:\n' "$#"
  [ "$#" -eq 0 ] || printf ' - <%s>\n' "$@"
}
IFS=:
set -o noglob
input $(cmd)
I got 3 arguments:
 - <a><a b>
 - <>
 - <b>< c>

Because, $(cmd) is unquoted, that's a split+glob operator. The shell retrieves the output of cmd, removes all the trailing newline characters, then splits that based on the value of $IFS special character, and then performs file name generation (for instance turns *.txt to the list of non-hidden txt files in the current directory) on the result words (that latter part not with zsh) and in the case of ksh also performs brace expansion (turns a{b,c} into ab and ac for instance).

The default value of $IFS contains the SPC, TAB and NL character (also NUL in zsh). Those (not NUL) also happen to be IFS-white-space character, which are treated specially when it comes to IFS-splitting.

If the output of cmd is " a b\nc \n", that split+glob operator will generate a "a", "b" and "c" arguments to ./input. With IFS-white-space characters, it's impossible for split+glob to generate an empty argument. To generate an empty argument, you'd need to choose a separator that is not an IFS-whitespace character. Actually, any character but SPC, TAB or NL will do (best to also avoid multi-byte characters which are not supported by all shells here).

IFS=: # split on : which is not an IFS-whitespace character
set -o noglob  # disable globbing (also brace expansion in ksh)
./input $(cmd)

And if cmd outputs a::b\n, then that split+glob operator will result in a "a", "" and "b" arguments (note that the "s are not part of the value, I'm just using them here to help show the values).

With a:b:\n, depending on the shell, that will result in "a" and "b" or "a", "b" and "". You can make it consistent across all shells

cmd() {
  printf 'a::b\n'
}
input() {
  printf 'I got %d arguments:\n' "$#"
  [ "$#" -eq 0 ] || printf ' - <%s>\n' "$@"
}
IFS=:
set -o noglob
input $(cmd)
I got 3 arguments:
 - <a>
 - <>
 - <b>

Because, $(cmd) is unquoted, that's a split+glob operator. The shell retrieves the output of cmd, removes all the trailing newline characters, then splits that based on the value of the $IFS special parameter, and then performs filename generation (for instance turns *.txt into the list of non-hidden txt files in the current directory) on the resulting words (that latter part not with zsh) and in the case of ksh also performs brace expansion (turns a{b,c} into ab and ac for instance).

The default value of $IFS contains the SPC, TAB and NL characters (also NUL in zsh). Those (not NUL) also happen to be IFS-whitespace character, which are treated specially when it comes to IFS-splitting.

If the output of cmd is " a b\nc \n", that split+glob operator will generate a "a", "b" and "c" arguments to ./input. With IFS-white-space characters, it's impossible for split+glob to generate an empty argument because sequences of one or more IFS-whitespace characters are treated as one delimiter. To generate an empty argument, you'd need to choose a separator that is not an IFS-whitespace character. Actually, any character but SPC, TAB or NL will do (best to also avoid multi-byte characters which are not supported by all shells here).

IFS=:          # split on ":" which is not an IFS-whitespace character
set -o noglob  # disable globbing (also brace expansion in ksh)
./input $(cmd)

And if cmd outputs a::b\n, then that split+glob operator will result in "a", "" and "b" arguments (note that the "s are not part of the value, I'm just using them here to help show the values).

With a:b:\n, depending on the shell, that will result in "a" and "b" or "a", "b" and "". You can make it consistent across all shells with

./input $(cmd)""

(which also means that for an empty output of cmd (or an output consisting only of newline characters), ./input will receive one empty argument as opposed to no argument at all).

cmd() {
  printf 'a b:: c\n'
}
input() {
  printf 'I got %d arguments:\n' "$#"
  [ "$#" -eq 0 ] || printf ' - <%s>\n' "$@"
}
IFS=:
set -o noglob
input $(cmd)
I got 3 arguments:
 - <a b>
 - <>
 - < c>
Source Link
Stéphane Chazelas
  • 584.8k
  • 96
  • 1.1k
  • 1.7k
Loading