11

I basically want to write me a bash script, where I'd generate a couple of big files using heredoc; and then run some commands using those files.

It is understood that (obviously) the heredoc files need to be generated before the commands run - however, what irritates me in that arrangement, is that I must also write the 'heredoc' statements code, before I write the command code.

So I thought I'd write the heredoc statements in a function - but still the same problem here: Chapter 24. Functions says:

The function definition must precede the first call to it. There is no method of "declaring" the function, as, for example, in C.

Indeed, it is so:

$ cat > test.sh <<EOF
testo

function testo {
  echo "a"
}
EOF

$ bash test.sh 
test.sh: line 1: testo: command not found

Then I thought maybe I could place some labels and jump around with GOTO, as in (pseudocode):

$ cat > test.sh <<EOF
goto :FUNCLABEL

:MAIN
testo

goto :EXIT

:FUNCLABEL
function testo {
  echo "a"
}
goto MAIN

:EXIT

... but it turns out BASH goto doesn't exist either.

My only goal is that - I want to first write the "core" of the script file, which is some five-six commands; and only then write the heredoc statements in the script file (which may have hundreds of lines); having the heredocs first really makes reading the code difficult for me. Is there any way to achieve that?

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
sdaau
  • 36,975
  • 46
  • 198
  • 278

3 Answers3

25

A common technique is:

#!/bin/sh

main() {
  cmd_list
}

cat > file1 << EOF
big HEREDOC
EOF

main "$@"
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • 1
    Awesome, @William Pursell - many thanks for that! And it's quite simple really - one just has to think about wrapping the main "cmd_list" instead of wrapping the heredocs... Many thanks again - cheers! – sdaau Nov 23 '11 at 21:14
  • 1
    Just a note to self: here is (more-less) the same technique in Python: [Is it possible to forward-declare a function in Python? - Stack Overflow](http://stackoverflow.com/questions/1590608/is-it-possible-to-forward-declare-a-function-in-python) – sdaau Nov 24 '11 at 00:08
  • Total Cygwin/bash scripting noob here, but I've found that I need to call main $@, otherwise I lose my command line args. Is this correct or am I missing something? – ManEatingCheese Aug 13 '15 at 23:49
  • 1
    @ManEatingCheese, no, you aren't missing anything. The command line arguments are not automatically carried into the function, and `main "$@"` is necessary. (Note the quotes, which are required to handle certain arguments, mostly those containing whitespace.) – William Pursell Aug 14 '15 at 16:55
4

In Bash you will have to define the entire function before calling it. If you want to write the core script first then you can write the heredoc statements in another script file and call it whenever you feel like and assign the values returned (may be) to your core script.

jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • Thanks for the comment, @Jaypal - but the reason I use heredocs in bash scripts is to avoid writing and calling other scripts - I want to have everything self-contained in one script instead.. Cheers! – sdaau Nov 23 '11 at 21:16
3

BASH scans the file linearly and executes statements as it comes across them, just like it does when you're on the command line. There are two ways I see to do what you want. First, you could write the code-generating heredoc, etc. in a separate file (say helperfile.sh) and source it with . helperfile.sh. That's probably best. You could also write a function (main perhaps) in the beginning that does what you want, then the heredoc code, then at the bottom call main.

Kevin
  • 53,822
  • 15
  • 101
  • 132
  • Thanks for that, @Kevin - for me, the `main` function is the answer (want to have everything one-script, now that I'm heredoc-ing); William Pursell just came in a bit earlier than you :) Cheers! – sdaau Nov 23 '11 at 21:20