E3F8 ‘read’ includes blanks in variable when it shouldn't · Issue #6406 · fish-shell/fish-shell · GitHub
[go: up one dir, main page]

Skip to content

‘read’ includes blanks in variable when it shouldn't #6406

@kseistrup

Description

@kseistrup

Observed behaviour

When read reads N variables from a string that holds N+1 variables if split by $IFS, variable number N will contain excess whitespace if more than one blank is separating the words.

E.g.: After Reading the string "A<space><tab><space>B<space><tab><space>C" into variables $A and $REST, $REST will contain "<tab><space>B<space><tab><space>C".

Expected behaviour

After Reading the string "A<space><tab><space>B<space><tab><space>C" into variables $A and $REST, $REST should contain "B<space><tab><space>C".

Relevant parts of read(1) says:

If  no  option  to  determine  how to split like --delimiter, --line or
--tokenize  is given, the variable IFS is used as a list  of characters
to split on. Relying on the use of IFS is deprecated and this behaviour
will be removed in future versions.

and

If there  are more  tokens  than  variables, the complete  remainder is
assigned to the last variable.

While I can see how the “the use of IFS is deprecated” and “the complete remainder” can be interpreted in more than one way, skipping all blanks and only putting "word<blank(s)>word" in the last variable is consistent with how a number of other shells – notably bash, dash, ksh, mksh, posh, sh, yash and zsh – are splitting a string into a number of words, and if fish's behaviour is intentional, I fail to see the logic or usefulness.

Examples

fish

$ cat read-test.fish
#!/bin/sh
# run with fish

# A<space><tab><space>B<space><tab><space>C
set TEST (printf 'A \t B \t C')
printf 'TEST="%s"\n' "$TEST"

# Assert that length of TEST is 1+3+1+3+1=9
printf 'len(TEST)=%s\n' (string length "$TEST")

# Let's read A into variable A and the rest into variable REST
echo "$TEST" \
| while read A REST
    printf 'A="%s"\n' "$A"
    printf 'REST="%s"\n' "$REST"
    printf 'len(REST)=%s\n' (string length "$REST")
  end

:
# eof
$ fish read-test.fish
TEST="A 	 B 	 C"
len(TEST)=9
A="A"
REST="	 B 	 C"
len(REST)=7

bash et al.

$ cat read-test.sh
#!/bin/sh
# run with bash, dash, ksh, mksh, posh, sh, yash, zsh

# A<space><tab><space>B<space><tab><space>C
TEST=$(printf 'A \t B \t C')
printf 'TEST="%s"\n' "$TEST"

# Assert that length of TEST is 1+3+1+3+1=9
printf 'len(TEST)=%s\n' "${#TEST}"

# Let's read A into variable A and the rest into variable REST
echo "$TEST" \
| while read A REST
  do
    printf 'A="%s"\n' "$A"
    printf 'REST="%s"\n' "$REST"
    printf 'len(REST)=%s\n' "${#REST}"
  done

:
# eof
$ bash read-test.sh
TEST="A 	 B 	 C"
len(TEST)=9
A="A"
REST="B 	 C"
len(REST)=5

Version(s)

$ fish --version
fish, version 3.0.2-1939-gea7868988
$ uname -a
Linux brainfreeze 5.4.2-arch1-1 #1 SMP PREEMPT Thu, 05 Dec 2019 12:29:40 +0000 x86_64 GNU/Linux
$ echo $TERM
xterm-256color
  • GNU bash, version 5.0.11(1)-release (x86_64-pc-linux-gnu)
  • dash 0.5.10.2
  • ksh 2020.0.0
  • mksh 57
  • posh 0.13.2
  • yash 2.49
  • zsh 5.7.1

📎 read-test.fish
📎 read-test.sh

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething that's not working as intended

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0