2

I have a case of twisted shell logic to submit to you, since I have found nothing on that particular point anywhere (please accept my apologies if I missed it). I'll try to explain the context as best I can.

I have a first scriptA which I expect to generate a second scriptB through the use of a heredoc. There are two items I want to have in this heredoc: a my_source file include, and some variables local to scriptA (for expansion within scriptA, that is). Here is an example:

scriptA:

#!/bin/sh
logfile=/path/to/my_logfile
scriptB=/path/to/my_script
cat > ${scriptB} << __EOF__
  . /path/to/my_source  #this is a shell script
  echo "Some text" | tee -a ${logfile}
__EOF__

My question on the snippet above is: will shell expansion on the . instruction (i.e. inclusion of my_source) occur in scriptA or in scriptB?

Bonus: is it possible to specify somehow that some part of the here doc should not be expanded?

Note: I tried to be POSIX-compliant here and avoid bash specifics

Thanks for the insights!

EDIT: Answer is that the . utility shall not trigger in the here-doc in scriptA. This is because a here-doc only performs:

parameter expansion, command substitution, and arithmetic expansion

The . is a shell special built-in utility, which is not expanded (just like all shell built-ins, including bash-, ksh-, tcsh-specific (...) built-ins).

Thanks @ilkkachu for the insight.

1

No, a here-doc is expanded mostly like a double-quoted string:

If no part of word is quoted, all lines of the here-document shall be expanded for parameter expansion, command substitution, and arithmetic expansion.

Backslashes also work to escape special characters.

The note about quoting means that something like <<"EOF" would prevent expanding anything within the here-doc. In your example, the reference to ${logfile} would be expanded by the shell before passing the input to cat.

You could still use command substitution if you want to include the output of a command, but if all you want is that, using a pipe would also be a logical choice.

  • I was assuming the . would fall under the command substitution definition, e.g. expanded before the here-doc creation. Thanks for the quick comment! – Meeshkah Mar 30 '17 at 11:36
  • 1
    @Meeshkah, nope. Even though it has an unusual name, it's just a builtin command (strictly speaking, a special built-in utility, but the difference is minor). – ilkkachu Mar 30 '17 at 11:50
  • ok I see the difference now, thank you. Can you expand on your suggestion to use a pipe in your OP? I'm not sure I get this 'choice' – Meeshkah Mar 30 '17 at 11:57
1

The heredoc doesn't do re-interpretation or you can say, doesn't run any commands inside it. It just interpolates strings.

So the answer to your query is that the source-ing will not happen inside the heredoc.

As for the latter, you can make use of \ i.e., backslashes to turn OFF the meaning of characters you don't want expanded by the heredoc.

  • OK, what would happen if I escaped the . command: \. /path/to/my_source? Would the backslash be included in the here-doc b/c the . is not recognized as a command? – Meeshkah Mar 30 '17 at 11:38
  • Nothing would happen. The \ would be found attached to the . and that's it. I would urge you to consider the heredoc as a multiline variable being double quote interpolated. (unless there's a \heredoc) – user218374 Mar 30 '17 at 22:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.