$ 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 

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
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?


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

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



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


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"

(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:

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 `''

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"

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.