1

I personally work cross platform with Windows and Linux and sometimes I edit .sh files with Notepad++. It is hence problematic for me to keep all my files' tab indents as Unix-like so my solution was to use space-based indenting.

Yet, I encounter problem when indenting herdocs inside heredocs. For example, here is an external heredoc, holding an internal cat heredoc:

bash /dev/fd/10 10<<-'EOT'
    Some command.
    cat << EMW >> /etc/apache2/apache2.conf
    EMW
    Some other command.
EOT

As I recalled I ran this successfully with Unix-like tabbing in bash, but not with Windows-like tabbing as then the script broke and the same goes for using spaces.

My question:

My question can actually be comprised of these questions and I ask it not only for me but for other curious people to find this:

  1. Why can't we use spaces for indenting commands and heredocs inside other heredocs?
  2. If I'm wrong and there is a workaround to allow space indenting for commands and heredocs inside other heredocs, than what is it?
  • Yes @roaima, I think I confused with something else. This topic is quite hard for because I didn't find much didactic learning material on this and was confused a few times regarding this. I edited my question. I asked this question after I felt the last previous one didn't reflect what I actually wanted to know. –  Mar 22 '17 at 21:44

1 Answers1

3

First of all, there is no such thing as a Unix-like tabulation or a Windows-like tabulation. A tabulation character is the same in Windows and Unix. What may change among text editors (not among OSes), is 1. what happens when you hit the TAB key or 2. how many spaces are displayed when the editor meets a tabulation character in the source code. A rule of thumb is to set indentation to whatever you like (in number of spaces) and to keep tabulation to 8, but this is another debate.

Now, back to your code. The problem is the EMW delimiter. With this syntax of yours, the EMW line can not be indented (be it with spaces or TABs), it must be at the beginning of a line. Else, it loses its heredoc delimiter status.

So, one solution could be:

bash /dev/fd/10 10<<'EOT'
    Some command.
    cat << EMW >> /etc/apache2/apache2.conf
....
....
EMW
    Some other command.
EOT

Note also that the content of apache2.conf (symbolized above with ....) must not be indented, or it would be indented in apache2.conf too.

If you want to indent the whole bash code, use this syntax instead:

bash /dev/fd/10 10<<-'EOT'
        Some command.
        cat << EMW >> /etc/apache2/apache2.conf
        ....
        ....
        EMW
        Some other command.
EOT

Here, leading space used for indentation is composed of any number of the TAB character (TAB, not space!)

What did I change? I changed 10<<'EOT' to 10<<-'EOT'. This special syntax asks bash to discard any leading TAB character while parsing a heredoc. The EMW delimiter can then be indented, as well as the content of apache2.conf.

xhienne
  • 17,793
  • 2
  • 53
  • 69
  • Thank you. I mistakenly forgot to put the hyphen symbol in the question. Yoyu say that I just need to add that and use tabulation? If so, I must change Notepad++ from spaces, to tabs... And you say there is a hueristic to follow tabulation of 8 spaces... I was sure it's 2 or 4... You have sure enlightened me. I hope I understand right. –  Mar 22 '17 at 20:28
  • Don't mix up tabulation with indentation. A tabulation character should remain a tabulation character (no substitution with X spaces) and should preferably be equal to 8 spaces. Don't change your settings regarding the tabulation. You may use whatever number of spaces to indent your code though. Just ensure that you get a true tabulation when you press the TAB key, that's all. In the heredoc <<-, you must prefix your lines with a TAB character, or that would not work. – xhienne Mar 22 '17 at 20:36
  • You explain this very didactically. I salute you! I really want to ask you, just to make sure I fully get this --- How will you explain the difference between "tabulation" to "indentation"? As I see it, Each time we indent in the "traditional" way we make a tabulation (to be distinguished from "nontraditional" indentation made with 4 spaces in one tab hit, as possible with notepad++)... –  Mar 22 '17 at 20:46
  • 1
    Thank you. I haven't enough time and space to answer thoroughly. Indentation is the way you "decorate" your program by giving an offset to inner blocks of code (this offset may be made of spaces or tabulations). Tabulation is a special character, and a special key, that makes the following text jump to the nearest predefined position on the right (usually a multiple of eight characters). It can be used to indent your code. Google for "indentation vs tabulation" for further explanation. – xhienne Mar 22 '17 at 20:58
  • 1
    You might want to answer here as well; I plan to give bounty on this one: http://unix.stackexchange.com/questions/353076/how-to-indent-an-heredoc-inside-an-heredoc-the-right-way –  Mar 24 '17 at 07:26
  • OK, I've just put my answer there, but it's not very different from this one here. Just more detailed. – xhienne Mar 24 '17 at 21:31
  • Maybe I missed that fact when I recalled the times I didn't have this knowledge and understanding why my script breaks each slightly different execution, so I wanted to make sure I am not misleading anyone in my phrasing above and that I get an answer to the direct question of "How to indent an heredoc inside an heredoc?". I should now test that as I remember I did do the second code example you did above (tabulating everything inside the external heredoc, including the internal heredoc with tabs), but it might have been an End Of Line (EOL) problem or something else from Notepad++ (Windows). –  Mar 25 '17 at 08:22
  • @Benia Or notepad++ turns your tabulation into spaces (I don't know notepad++, but some editors offer this possibility). This would break the <<- syntax. – xhienne Mar 25 '17 at 10:50