Tricky brace expansion in shell

前端 未结 4 1027
野趣味
野趣味 2021-01-02 11:34

When using a POSIX shell, the following

touch {quick,man,strong}ly

expands to

touch quickly manly strongly
<
相关标签:
4条回答
  • 2021-01-02 11:48

    In bash, you can do this:

    #!/bin/bash
    TEST=quick,man,strong
    eval echo $(echo {$TEST}ly)
    #eval touch $(echo {$TEST}ly)
    

    That last line is commented out but will touch the specified files.

    0 讨论(0)
  • 2021-01-02 11:59

    Zsh can easily do that:

    TEST=quick,man,strong
    print ${(s:,:)^TEST}ly
    

    Variable content is splitted at commas, then each element is distributed to the string around the braces:

    quickly manly strongly
    
    0 讨论(0)
  • 2021-01-02 11:59

    Taking inspiration from the answers above:

    $ TEST=quick,man,strong
    $ touch $(eval echo {$TEST}ly)
    
    0 讨论(0)
  • 2021-01-02 12:00

    ... There is so much wrong with using eval. What you're asking is only possible with eval, BUT what you might want is easily possible without having to resort to bash bug-central.

    Use arrays! Whenever you need to keep multiple items in one datatype, you need (or, should use) an array.

    TEST=(quick man strong)
    touch "${TEST[@]/%/ly}"
    

    That does exactly what you want without the thousand bugs and security issues introduced and concealed in the other suggestions here.

    The way it works is:

    • "${foo[@]}": Expands the array named foo by expanding each of its elements, properly quoted. Don't forget the quotes!
    • ${foo/a/b}: This is a type of parameter expansion that replaces the first a in foo's expansion by a b. In this type of expansion you can use % to signify the end of the expanded value, sort of like $ in regular expressions.
    • Put all that together and "${foo[@]/%/ly}" will expand each element of foo, properly quote it as a separate argument, and replace each element's end by ly.
    0 讨论(0)
提交回复
热议问题