mainThe GNU Bourne-Again SHell - Support: sr #108956, Lone trailing input field...

 
 

sr #108956: Lone trailing input field separator is stripped by read (bash >=3)

Submitter:  Chris Taylor <cttttt>
Submitted:  Sat 23 Jan 2016 12:54:21 AM UTC
   
 
Category:  None Priority:  5 - Normal
Severity:  3 - Normal Status:  Invalid
Privacy:  Public Assigned to:  None
Open/Closed:  Open Operating System:  GNU/Linux
* Mandatory Fields

Add a New Comment Rich Markup
   

Tue 26 Jan 2016 08:00:18 PM UTC, comment #1: 

This was clarified by the Posix working group back in 2005.  The characters in $IFS are delimiters, and the delimiters are field terminators.  There is some special-casing done with IFS whitespace, all described in the word splitting portion of the man page.

The `read' builtin uses the same rules as word splitting, so each instance of a delimiter terminates a field.  The text about leftover words and intervening separators applies to cases where there are more words in the input than variable arguments supplied to `read', which isn't the case in your examples.

Finally, I don't get anything close to your results going all the way back to bash-2.05b.  Both commands in your message result in

|foo|bar|

which is correct.  ksh, dash, mksh, and zsh all print the same thing.

Now, if you take the `null' variable out of your commands, I can see getting the results you do.  The Posix clarification happened between bash-2.05b and bash-3.2, so that's when the behavior changed to match the standard.

There is disagreement among shell implementations concerning the text `fewer vars than fields' but the Posix description of `read' (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html#tag_20_109) makes it pretty clear that bash is doing the right thing.

Chet Ramey <chet>
Group administrator
Sat 23 Jan 2016 12:54:21 AM UTC, original submission:  

Seems like when "read" is:

- Supplied a custom input field separator via IFS.
- Is given X variable names.
- Is given an input line with X (the same number of) fields.
- The input line is ends in a single input field separator.

...the trailing input field separator is trimmed.  However, where there are two or more trailing input field separators, they are left intact.  Seems like this inconsistency started in Bash 3.


What do I do?
---

Run the following:

echo "foo=bar=" | while IFS== read name value null; do echo "|$name|$value|"; done
echo "foo=bar==" | while IFS== read name value null; do echo "|$name|$value|"; done


What happens?
---

In bash 2.05b.13(1)-release:

|foo|bar=|
|foo|bar==|

In bash 3.2.57(1)-release:

|foo|bar|
|foo|bar==|

In bash 4.3.42(1)-release:

|foo|bar|
|foo|bar==|


(( Also, POSIX-like shells that aren't bash (e.g. zsh) observe the bash2 behaviour. ))


What did I expect?




|foo|bar=|
|foo|bar==|

According to the documentation, for the "leftover words and their intervening separators assigned to the last name," supplied to read.

Chris Taylor <cttttt>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by chet (Posted a comment)
  • -email is unavailable- added by cttttt (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follows 1 latest change.

    Date Changed by Updated Field Previous Value => Replaced by
    2016-01-26 chet StatusNone Invalid

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code