Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.
$ sh bashtrrrrrr 

# whats my pub. ip?
bashtrrrrrr: line 19: unexpected EOF while looking for matching `''
bashtrrrrrr: line 20: szintaktikai hiba:  váratlan fájl vég


$  cat bashtrrrrrr 
#!/bin/bash

echo '
# what's my pub. ip?
alias myip="curl -s "http://checkip.dyndns.org/" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -1"

# shorten ssh connection with tsocks
function t() { read THEIP; tsocks ssh root@$THEIP; }

# red/green terminals regarding exit code
export PROMPT_COMMAND='PS1="`
if [[ \$? = "0" ]];
then echo "\\[\\033[0;32m\\]";
else echo "\\[\\033[0;31m\\]";
fi`[\u@\h \w]\[\e[m\] "'

export PS1

' >> /home/USER/.bashrc

what am I missing?

share|improve this question
add comment

3 Answers 3

up vote 6 down vote accepted

Also putting the whole echo '...' command into

cat  <<'EOF' >> /home/USER/.bashrc

...

EOF

would help you to get rid the many of the internal quotes.

share|improve this answer
add comment

As the other answers mention, the issue is nested quotes.

I suggest you review how quoting works in bash. In short, quotes (of any kind, single quotes ', double quotes " or backticks `) are almost always matched with the first occurrence of a quote of the same kind; you have to escape a quote in order for it not to match (but you cannot escape single quotes ').

So, (1) the apostrophe in what's closes the single quote in echo ':

echo '
# what's my pub. ip?

In other words, your echo command ends after ... ip? and the rest is immediately executed by bash as a command, which is apparently not what you meant.

As Rajish' answer suggests, using here-documents solves many of the quoting issues:

echo >> /home/USER/.bashrc <<'__EOF__'
# what's my pub ip?
echo "we can nest quotes in here"
__EOF__

(2) Then, as already reported in ultrasawblade's answer, the quotes on this line do not match properly:

alias myip="curl -s "http://checkip.dyndns.org/" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -1"

You likely the want the first and the last " (double quote) characters on the line to match, but bash matches them in the order they are encountered on the line (left-to-right), so the double quote left of "http://... closes the quotes after alias myip=". Similarly, | grep -o and | head -1 are considered within quotes, and http://... and [0-9]*\.... are not. (This won't have any serious syntactical consequences in this case, apart from grep not seeing the backslashes, but keep it in mind for the future.)

One solution is to escape the double quotes (and also the backslashes, as backslashes do not lose their special meaning inside double quotes):

alias myip="curl -s \"http://checkip.dyndns.org/\" | grep -o \"[0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*\" | head -1"

Another workaround, which works in this case, is to use single quotes ' instead; either for defining the alias:

alias myip='curl -s "http://checkip.dyndns.org/" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -1'

or for the commands in the alias definition:

alias myip="curl -s 'http://checkip.dyndns.org/' | grep -o '[0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*' | head -1"

(3) Finally, at lines:

export PROMPT_COMMAND='PS1="`
if [[ \$? = "0" ]];

The ' (single quote) character after PROMPT_COMMAND= is interpreted as starting a new multi-line singly-quoted string, which ends at line:

fi`[\u@\h \w]\[\e[m\] "'

Thus, another singly quoted string is started by the ' character on the last line, but bash never sees a matching single quote. Thus you get the error:

unexpected EOF while looking for matching `''
share|improve this answer
add comment

Well, one problem is this line:

myip="curl -s "http://checkip.dyndns.org/" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -1"

bash is confused by the quotes in the middle of the string. When you put "quotes within quotes", you usually want to escape them, like so:

myip="curl -s \"http://checkip.dyndns.org/\" | grep -o \"[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\" | head -1"
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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