Search code examples
zshdouble-quotesparameter-expansion

double quotes in zsh parameter expansion


I have two test cases in zsh

  1. A. without quotes

    ~$ y=(${(f)$(echo -e "a b\nc d")}); printf "<%s>\n" "${y[@]}"
    <a b c d>
    
  2. B. with quotes

    ~$ y=(${(f)"$(echo -e "a b\nc d")"}); printf "<%s>\n" "${y[@]}"
    <a b>
    <c d>
    

However if I first assign the output of echo to a variable, the quotes do not have any effect:

  1. C. without quotes

    ~$ x=$(echo -e "a b\nc d"); y=(${(f)${x}}); printf "<%s>\n" "${y[@]}"
    <a b>
    <c d>
    
  2. D. with quotes

    ~$ x=$(echo -e "a b\nc d"); y=(${(f)"${x}"}); printf "<%s>\n" "${y[@]}"
    <a b>
    <c d>
    

Questions:

  1. comparing A and B, what causes the differences?
  2. comparing A and C, what causes the differences?

Solution

  • After some experiment, I feel the following rules may have been applied

    Sec1. direct use

    1. A. without quotes

      ~$ y=(${(f)$(echo -e "a b\nc d")}); printf "<%s>\n" "${y[@]}"
      <a b c d>
      

      unquoted $() produces words split by IFS: see http://zsh.sourceforge.net/Doc/Release/Expansion.html#Command-Substitution

    2. B. with quotes

      ~$ y=(${(f)"$(echo -e "a b\nc d")"}); printf "<%s>\n" "${y[@]}"
      <a b>
      <c d>
      

      quoted $() produces a single string

    Sec2. assignment to scalar

    1. C. without quotes

      ~$ x=$(echo -e "a b\nc d"); y=(${(f)${x}}); printf "<%s>\n" "${y[@]}"
      <a b>
      <c d>
      

      when being assigned to a scalar, it works as automatically quoted

    2. D. with quotes

      ~$ x=$(echo -e "a b\nc d"); y=(${(f)"${x}"}); printf "<%s>\n" "${y[@]}"
      <a b>
      <c d>
      

      when being assigned to a scalar, it works as automatically quoted

    Sec3. assignment to array

    y=($(echo -e "a b\nc d"))

    Follows Sec1 http://zsh.sourceforge.net/Doc/Release/Expansion.html#Command-Substitution