0

When I execute this, I get just empty lines as output

# /bin/bash <<- EOF
while read a
do
    echo $a
done < /etc/fstab
EOF

If I copy the content of here-document into file and execute it, everything works as expected (I get content of /etc/fstab file).

Could anyone explain why?

UPDATE: Answering a question about why would I need to pass here-doc to bash this way, here is what I'm actually trying to do:

ssh user@host /bin/bash <<- EOF
       while read f; do
               sed -i -e "s/$OLD_VAL/$NEW_VAL/g" $f
       done < /tmp/list_of_files
EOF

Sed is complaining that $f is not set

6
  • 4
    What is the purpose of using a here-doc here ? oO Commented Nov 12, 2014 at 18:00
  • What I'm really trying to do pass a here-document to ssh "ssh user@root /bin/bash <<- EOF..." Commented Nov 12, 2014 at 18:02
  • I don't see that here. post relevant code. Commented Nov 12, 2014 at 18:03
  • 1
    I guess you need to quote EOF: write <<- "EOF", otherwise you'll have parameter expansion going on, your line echo $a will boil down to echo (unless a is set which is unlikely), and that's probably why you only see empty lines. Commented Nov 12, 2014 at 18:06
  • $file_conf is expanded by the shell before ssh is even called. A here document is a lot like a double-quoted string. Commented Nov 12, 2014 at 18:47

3 Answers 3

4

In case someone bumps into this, here is a version that works:

# /bin/bash <<- EOF
while read a
do
    echo \$a
done < /etc/fstab
EOF

The variable a is not defined in the parent bash script. It will be substituted with empty value before the here-document will be passed to a child bash. To avoid substitution a $-sign should be escaped with "\".

Sign up to request clarification or add additional context in comments.

1 Comment

Alternatively, single-quote the here-doc terminator: bash <<- 'EOF'
0

You dont need here document here. If you were trying a script you could do:

#!/bin/bash
while read a
do
    echo "$a"
done < /etc/fstab

Comments

0

I do not have enough reputation here to add comments, so I am forced to answer instead.

First, you have multiple levels of shell going on. In your initial example, the syntax for your HERE doc was incorrect, but your edited update was correct. The <<- will remove one leading tab character (but not spaces) from each line of text until your EOF delimiter (which could have been named anything). Using << without the '-' would expect each line of the HEREdoc to start in column 0.

Next, you are using ssh getting your shell from a remote host. This also implies that your /tmp/list_of_files will also exist on the remote machine. This also means any local shell meta-character should be escaped to ensure it is passed to the program/location where you actually want it expanded.

I do not believe a HEREdoc is necessary, when you can pass a complete semicolon separated one-liner to ssh. This may also afford you some flexibility to let your local shell do some expansion before variables are passed to ssh or your remote shell.

OLD=' '
NEW=$'\t'
ssh -q user@host "for filename in \$(</tmp/list_of_files); do gsed -i.\$(date %s) -e 's/'$OLD'/'$NEW'/g' \$filename; done"

Let's not forget the -i is an in-place edit, not a flag to ignore the upper/lower case of our regex match. I like to create backups of my files any time I edit/change them so I have a history if/when anything breaks later.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.