0

I'm looking for a simple way to include multi-line scripts inline in documentation to make it transparent what each step does.

This works

echo "echo 1234" | bash

So does this

echo 'for N in 1 2 3; do echo $N; done' | bash

However, I'd like to use something like this (which does not work):

echo <<EOF | bash
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

Update, the closest working solution so far is:

cat <<EOF|bash
for N in 1 2 3 4; do
    echo "N is now \$N"
done
EOF

Ideally though I'd like to not have to escape the \$N

A correct solution will not:

  • use tools not installed default debian config
  • involve a temp file
  • downloaded the script ( curl -o - htpp://blah.com/script | bash etc )

Ideally it's something something the reader can copy paste, press enter, and will execute without further action.

1

If you quote or escape the here-document delimiter (i.e. <<'EOF' or <<\EOFinstead of just <<EOF), the shell won't do expansions (of variables etc) on the content.

cat <<'EOF' | bash
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

BTW, the cat command isn't really doing anything useful here (it's what's known as a "useless use of cat", or UUoC). You can eliminate it and send input directly to bash:

bash <<'EOF'
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

If the snippet needs to read input, that's a little tricky because the script's input is... the script snippet itself. On most unix-like OSes, you can avoid this by passing the script over a different file descriptor, and telling bash to "execute" that file descriptor:

bash /dev/fd/3 3<<'EOF'
read -p "Enter something here: " input
echo "You entered: ${input}"
EOF

But note that any variables set in one of these snippets (like $input here) are only set in that one shell process, and will be lost when it exits.

| improve this answer | |
  • fantastic answer TIL alot. Thank you – Nanzikambe Mar 10 at 10:45
1

I think the best you can do is something like this:

bash -c '
    echo "Simple scriptlike thingy"
    for I in 1 2 3 45; do
      echo "I is now ${I}"
    done
'

Note that this essentially gives the while script as a parameter to the -c switch, and this parameter itself will be parsed by bash. This is why you can't use " signs like this:

bash -c "
    THING=text
    echo this will not work: $THING
"

because in the parameter, $THING is substituted before passed as argument, and since THING is unset, it will be replaced to an empty string. A string enclosed in apostrophes is not parsed, so it can be used to contain variables to be set when the "second bash process" parses the script.

For more complex scripts, I think the best way would be to ask your readers to save the script and run it, but for simple constructs, the above should work.

| improve this answer | |
  • thanks for the answer, bash -c 'blah' will work for 90% of my needs, I'm going to hold out for a while for an answer which allows both " and ' -- just in case – Nanzikambe Mar 7 at 13:25

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.