bug-bash
[Top][All Lists]
Advanced

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

Re: Incorrect alias expansion within command substitution


From: Robert Elz
Subject: Re: Incorrect alias expansion within command substitution
Date: Sat, 05 Feb 2022 04:16:07 +0700

    Date:        Fri, 4 Feb 2022 21:06:11 +0100
    From:        Alex fxmbsw7 Ratchev <fxmbsw7@gmail.com>
    Message-ID:  
<CAALKErH2N+EiVW+=sVBNYrpYa5JiWVrVjCe1YT=NEgUuJcRitA@mail.gmail.com>


  | now changing this to dynamic eof marker

There is no such thing.   Unlikely (*VERY* unlikely) there ever will be.

  | cat <<$( printf leet )
  | $(  printf leet )
  | $( printf leet )
  | notice the two spaces in the middle to not match eof

Yes, that is supposed to work, and "cat" should write a single
line containing "leet".   The end word is *never* expanded, not
the copy of it after the << operator, and not the one that terminates
the here doc data (the former gets quote removal, but there are none
here to remove).

Since there are no quotes in the end word on the << operator, the
here doc text is expanded (when used, not when read - though in this
example it is used immediately when it is read, so that also makes no
apparent difference - but giving examples where it does is easy).
That includes expanding command substitutions inside the here doc
text (which does not include the end word).   The $(  printf leet )
produces "leet" on stdout, which replaces the command substitution
text in the here doc, so cat reads (and outputs) the single line "leet".

  | thats valid code, cause eof is written twice ( the $( .. ) code )

No idea what you mean there - but yes, the end word must be written
twice, once after << and once after the here doc data.   If you're
counting the one that was inside the here doc (because it looks similar)
then that's pure co-incidence, that one could be anything, and while altering
that might change the input cat reads (and hence writes) it has no other
impact on anything at all.   You could even omit it entirely.

  | but
  |
  | cat <<$(  printf end )
  | $( printf end )
  | # here it should already end the heredoc parser

No it shouldn't.   The 2nd line there doesn't have enough spaces,
they're not the same.

The end word (after <<) is parsed as a command substitution, to find its
end, but is never expanded (the code in it is never executed) - all the
parsing accomplishes in this case is to allow the correct ')' to be found
so the command substitution text ends at the correct place - beyond that
it is ignored.

Perhaps a different example - I'm sure you know that in $(( )) you can
embed an arithmetic expression, and if you try and do something like

        $(( data 2 ))

you'll get a syntax error, because "data 2" is not a valid arithmetic
expression.

But collecting the text of arithmetic is done by simply looking for the '))'
that matches the '((' after the opening '$' (taking account of any other
parentheses that might exist in the expression).   The actual arithmetic isn't
evaluated (or parsed) until it is to be expanded - it is simply a string.

That means you can do (should be able to do, not all shells work properly)

    cat <<$(( any random trash *$ ^%%\ # you like - except for parentheses ))

and it should work fine (the here doc text ends with the exact same string,
spacing and all).   Even the "except for parentheses" just means that any
parentheses that occur must balance correctly - otherwise the correct '))'
won't be detected.

kre





reply via email to

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