为什么我不能运行这个脚本?

Lan*_*nes 0 bash quoting

$ 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
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Ric*_*rri 11

正如其他答案所提到的,问题是嵌套引号。

我建议你回顾一下 bash 中的引用是如何工作的。简而言之,引号(任何类型的单引号'、双引号"或反引号 `)几乎总是与第一次出现的相同类型的引号匹配;您必须转义引号才能使其不匹配(但您不能转义单引号')。

因此,(1) 中的撇号what's关闭了 中的单引号echo '

echo '
# what's my pub. ip?
Run Code Online (Sandbox Code Playgroud)

换句话说,您的echo命令在之后结束... ip?,其余部分立即由 bash 作为命令执行,这显然不是您的意思。

正如Rajish 的回答所暗示的那样,使用here-documents解决了许多引用问题:

echo >> /home/USER/.bashrc <<'__EOF__'
# what's my pub ip?
echo "we can nest quotes in here"
__EOF__
Run Code Online (Sandbox Code Playgroud)

(2) 然后,正如Ultrasawblade 的回答中已经报告的那样,此行上的引号不正确匹配:

alias myip="curl -s "http://checkip.dyndns.org/" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -1"
Run Code Online (Sandbox Code Playgroud)

您可能希望行中的第一个和最后一个"(双引号)字符匹配,但是 bash 按照它们在行上遇到的顺序(从左到右)匹配它们,因此左双引号"http://...关闭引号之后alias myip="。同样,| grep -o| head -1被认为是 报价,而http://...[0-9]*\....不是。(在这种情况下,除了grep看不到反斜杠之外,这不会产生任何严重的语法后果 ,但请记住以备将来使用。)

一种解决方案是转义双引号(以及反斜杠,因为反斜杠在双引号内不会失去其特殊含义):

alias myip="curl -s \"http://checkip.dyndns.org/\" | grep -o \"[0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*\" | head -1"
Run Code Online (Sandbox Code Playgroud)

在这种情况下有效的另一种解决方法是改用单引号 ';要么用于定义别名:

alias myip='curl -s "http://checkip.dyndns.org/" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -1'
Run Code Online (Sandbox Code Playgroud)

或者对于别名定义中的命令:

alias myip="curl -s 'http://checkip.dyndns.org/' | grep -o '[0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*' | head -1"
Run Code Online (Sandbox Code Playgroud)

(3) 最后,在行:

export PROMPT_COMMAND='PS1="`
if [[ \$? = "0" ]];
Run Code Online (Sandbox Code Playgroud)

'后面的(单引号)字符PROMPT_COMMAND=被解释为开始一个新的多行单引号字符串,该字符串在行结束:

fi`[\u@\h \w]\[\e[m\] "'
Run Code Online (Sandbox Code Playgroud)

因此,另一个单引号字符串由'最后一行的字符开始,但 bash 从未看到匹配的单引号。因此你得到错误:

unexpected EOF while looking for matching `''
Run Code Online (Sandbox Code Playgroud)


Raj*_*ish 6

还将整个echo '...'命令放入

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

...

EOF
Run Code Online (Sandbox Code Playgroud)

将帮助您摆脱许多内部引号。