在某些情况下,bash(或其他shell)脚本中的空格数量确实很重要


14

有人告诉我空格在bash其他shell脚本中很重要,除非我知道自己在做什么,否则不要更改空格的存在。“改变存在”是指在两个非空格字符之间插入一个空格,或者在两个非空格字符之间删除一个空格,例如更改var="$val"var ="$val",反之亦然。我想问一下

在shell脚本中使用单个空格或使用多个连续空格会有所不同吗?

(当然,在引号中插入/删除空格会有所不同,例如从更改为echo "a b"echo "a b"反之亦然。我正在寻找除此琐碎示例以外的示例。)

我遇到了这个问题,但是那是关于在两个非空格字符之间添加和删除空格的问题,我知道很多例子会有所作为。

任何帮助,将不胜感激。如果可能,包括更多种类的贝壳。

Answers:


19

在引号之外,shell使用空格(空格,制表符,换行符,回车符等)作为单词/令牌分隔符。这意味着:

  • 没有用空格分隔的事物被认为是一个 “单词”。
  • 用一个或多个空格字符分隔的事物被视为两个(或多个)单词。

只要至少有一个,“事物”之间的空格字符的实际数量就无关紧要。


谢谢。我自己找不到任何反例。我只是想确定一下。

2
Bash还将换页和垂直制表符视为空白。
fpmurphy

真正。我最初写了“ ...换行符”,然后将其更改为显式添加回车符。不小心掉了“等”。
cas

如果空格数量太大而导致程序无法放入内存怎么办?
Worse_Username

7
@Worse_Username空格不必容纳在内存中。我刚刚在具有8GB RAM和20GB交换空间的计算机上创建了48GB脚本。运行得很好。确实花了3分钟来处理所有空白,但最后,它成功运行了一个echo命令,该命令在参数和参数之间留有足够的空白。
卡巴斯德(Kasperd),

23

这可能是作弊,但这:

rm foo\ bar         # "delete the file named 'foo bar'"

与此不同:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

即使空格不在引号中。;-)

更令人困惑的是:

rm \
    foo          # "delete the file named 'foo'"

与此不同:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

即使它们看起来相同!


即使空格不在引号中,反斜杠在功能上也类似于引号形式,我将其与问题的“琐碎示例”归为同一类。(尽管很有趣。)
David Z

12

如果我们不谈论空格字符(U+0020),但任何空白字符(U+0020\n\t等),然后一个特定的情况下,我想起:这里的文档。

这段代码(使用空格):

cat <<- 'EOF'
<space><space>foo
EOF

将打印:

  foo

但是此代码(使用标签):

cat <<- 'EOF'
<tab><tab>foo
EOF

将打印:

foo

这是因为(如POSIX所述):

如果重定向操作符为<<-,则应从输入行和包含尾部定界符的行中删除所有前导<tab>字符。


1
这太有趣了。我想到了这里文档,但不认识<<-操作员。非常感谢你。

这里的文档是带引号的文本形式,而不是外壳代码。Shell分词不适用。
cas

2

在编写赋值语句时也有作用。就像我说的那样FOO=xyz,它将创建一个FOO以value 命名的环境变量xyz,但是如果我用空格分隔等号,它将认为我正在调用一个以FOOarg 命名的程序=xyz。因此,涉及某些语法确实很重要。


通常FOO=xyz不会创建内部shell变量,但不会创建环境变量。您需要set -aexport FOO=xyz为此(即使其成为非subshel​​l子进程环境的一部分)。
Hauke Laging,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.