bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: why must non-standard $IFS members be treated so differently ?


From: Dan Douglas
Subject: Re: why must non-standard $IFS members be treated so differently ?
Date: Sun, 29 Jul 2012 10:02:54 -0500
User-agent: KMail/4.8.3 (Linux/3.4.6-pf+; KDE/4.8.3; x86_64; ; )

On Sunday, July 29, 2012 03:23:29 PM Jason Vas Dias wrote:
> Good day Chet, list -
>  I'm concerned about the difference in output of these functions with
> the example input
>  given on the '$' prefixed line below (with 4.2.29(2)-release
> (x86_64-unknown-linux-gnu)):
> 
>      function count_args     {                v=($@);  echo ${#v[@]}; }
> 
>      function count_colons {  IFS=':' ;    v=($@);  echo ${#v[@]}; }
> 
>  $ echo $(count_args 1 2 3\ 4) $(count_colons 1:2:3\:4)
>  3 4
> 
>  It appears to be impossible for an item delimited by 'X' to contain
> an escaped  'X' ('\X')  if 'X' is not
>  a standard delimiter (' ', '<TAB>') .  Quoting doesn't seem to help either:
> 
>  $ echo $(count_args 1 2 3\ 4) $(count_colons 1:2:3':4')
>  3 4
> 
> To me, this appears to be a bug.
> 
> But I bet you're going to tell me it is a feature ?
> Please explain.

Bash doesn't re-parse the results of expansions for quotes or escaping. When 
you expand something unquoted, the entire result is always subject to 
word-splitting. 

In the case of `count_args 1 2 3\ 4', you are passing 3 arguments. The 
backslash is not the result of expansion , so it gets treated as escaping a 
space. Note this is because bash is pass-by-value, this escaping/expansion is 
processed prior to calling the function.

In the case of `count_colons 1:2:3\:4', you are passing one argument. The shell 
strips away the backslash when the function is called (just as it did in the 
first example), so the argument being passed is actually '1:2:3:4'

 $ printf '%s\n' 1:2:3\:4
1:2:3:4

If you wanted to pass the backslash, you would have to either quote the 
argument, or use \\.

However in either case, you're going to have 4 arguments, because as previously 
stated, escape characters  resulting from expansions are not treated as escapes.

 $ f() { IFS=: local -a 'v=( $@ )'; printf '<%s> ' "${v[@]}"; echo; }; f 
1:2:3\:4
<1> <2> <3> <4>
 $ f() { IFS=: local -a 'v=( $@ )'; printf '<%s> ' "${v[@]}"; echo; }; f 
1:2:3\\:4
<1> <2> <3\> <4>

See also my answer to this recent question: http://superuser.com/a/454564/78905
-- 
Dan Douglas

Attachment: signature.asc
Description: This is a digitally signed message part.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]