如何在bash中学习如何引用?

Joh*_*den 3 bash eval quote

在编写bash脚本时,我一直对引用和评估的规则感到困惑.我知道一些基础知识,比如''和'"与``之间的区别,但我似乎仍然经常出错,并且试图尝试各种不同的方式来说同样的事情.

我通常可以通过蛮力解决任何个别问题,但我认为我的工作原理的概念模型必须以一种未知的方式无可救药地打破.

我对lisp的引用,评估,阅读,打印,语法报价系统没有任何问题.事实上,我写了一个小卡塔,以帮助人们了解发生了什么:http://www.learningclojure.com/2010/11/syntax-quote-kata-for-confused.html

我想我正在为bash寻找类似的东西(这看起来要复杂得多).一个好的模型或一组练习将帮助我形成这样一个模型,这将使​​我能够看到一个复杂的shell脚本,其中变量被转换和评估,打印出来并读取,并找出将要发生的事情无需尝试.

如果做不到这一点,调试过程的好方法,以及在评估的每个阶段观察正在发生的事情都会非常有帮助.

l0b*_*0b0 9

Bruce Barnett的UNIX Shell引用教程很棒,而Bash FAQ/陷阱/单词分裂文章有很多有用的提示.简短摘要:

不带引号的字符串可以包含大多数字符,但不是全部(如换行符),并且必须对其中的许多字符(包括空格)进行转义.只是不要使用它们 - 如果你陷入诱惑,你可能会发现修改脚本的人在必要时忘记包含引号.

单引号字符串可以包含大多数字符,包括NUL和换行符,但不包含单引号,因此它们也仅对简单值有用.

反引号用于命令.只有在shell不支持的情况下才能使用它们$().例:

current_dir=`pwd` # BAD! Don't do this!
Run Code Online (Sandbox Code Playgroud)

该命令很糟糕,因为当没有引用赋值的右侧时,shell会对其执行分.它经常导致难以重现的错误,因为空格很难在视觉上检查.要引用命令,必须使用双引号:

current_dir="$(pwd)" # OK, but loses newlines at EOF
Run Code Online (Sandbox Code Playgroud)

EOF的换行特别棘手.您可以添加单个字符并使用例如剥离它

# Works for some commands, but not pwd
current_dirx="$(pwd; echo x)"
current_dir="${current_dirx%x}"
printf %s "$current_dir"
Run Code Online (Sandbox Code Playgroud)

,但有一个额外的困难,因为一些指令(像pwd)将在其输出端增加一个换行符无论如何,所以你可能需要删除,以及:

# Works for some commands, including pwd
current_dirx="$(pwd; echo x)"
current_dir="${current_dirx%$'\nx'}"
printf %s "$current_dir"
Run Code Online (Sandbox Code Playgroud)

双引号可以包含任何字符(Try echo -ne "\0" | wc -c),但请注意,变量不能包含NUL字符.

ANSI-C引号可以包含除NUL(Tryecho -ne $'\0' | wc -c)之外的任何字符,并提供方便的转义码,以便更容易使用特殊字符:

printf %s $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
printf %q $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
touch -- $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
rm -- $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
Run Code Online (Sandbox Code Playgroud)