[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
signature.asc
Description: This is a digitally signed message part.