bug-bash
[Top][All Lists]
Advanced

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

Re: Strange compgen behaviour


From: Bernd.Eggink
Subject: Re: Strange compgen behaviour
Date: Fri, 25 Sep 2009 21:42:55 +0100
User-agent: Thunderbird 2.0.0.22 (Windows/20090605)

Chet Ramey schrieb:
Bernd Eggink wrote:
Chet Ramey schrieb:
Hm, compgen appears to behave strange if words contain whitespace.
Well, it splits the argument to -W on $IFS as documented.  What other
strange behavior do you see?
For example, this:

    function _aha
    {
        local list="a b:c d:e f"
        COMPREPLY=($(IFS=: compgen -W "$list"))
    }

    complete -F _aha aha

Typing aha <Tab> cycles through 6 items a, b, c, d, e, f, whereas I
would expect 3 items 'a b', 'c d', 'e f'. It looks like compgen splits
the argument to -W on $IFS _and_ whitespace. Or am I missing something?

I don't think you're considering the interaction between compgen,
command substitution, and compound array assignment.

I'll use the assignment to `list' you used above for the explanation.

compgen performs word splitting using $IFS and then outputs the results,
one word per line:

$ IFS=: compgen -W "$list"
a b
c d
e f

Command substitution takes that, chops off the last newline, and, since
it's unquoted, performs word splitting using $IFS on the result:

$ recho $(IFS=: compgen -W "$list")
argv[1] = <a>
argv[2] = <b>
argv[3] = <c>
argv[4] = <d>
argv[5] = <e>
argv[6] = <f>

If you want to preserve the embedded newlines, you have to quote the
expansion (but see below):

$ recho "$(IFS=: compgen -W "$list")"
argv[1] = <a b^Jc d^Je f>

When performing compound array assignments, though, the words between
the parens undergo all the shell word expansions, including word splitting:

$ COMPREPLY=( $(IFS=: compgen -W "$list") )
$ recho "${COMPREPLY[@]}"
argv[1] = <a>
argv[2] = <b>
argv[3] = <c>
argv[4] = <d>
argv[5] = <e>
argv[6] = <f>

So you can split on just the embedded newlines by setting $IFS:

$ oifs="$IFS"
$ IFS=$'\n' COMPREPLY=( $(IFS=: compgen -W "$list") )
$ IFS="$oifs"
$ recho "${COMPREPLY[@]}"
argv[1] = <a b>
argv[2] = <c d>
argv[3] = <e f>

Remember to save and restore $IFS, though, since the assignment to it
preceding the assignment to COMPREPLY will persist.

Chet,

thanks for the clarification. It's actually quite obvious and I should have seen it myself.

Regards,
Bernd




reply via email to

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