8. 扩展符

示例:

$ echo *

这里输出当前目录下的所有文件,而不是输出 * 号。因为 shell 会在命令执行结果输出前自动解析命令行中的指定字符。

路径名扩展符

示例:

$ echo D*
$ echo *s
$ echo [[:upper:]]*
$ echo /usr/*/share

波浪号~扩展

~ 在单词开头表示指定用户的家目录,如果未指定用户名,则表示当前登录用户的家目录,如:echo ~foo 输出 /home/foo(如果 foo 用户存在)。

算术扩展

示例:

$ echo $((2 + 2))

格式:

$ $((expression))

只支持整数,空格在表达式中无意义,表达式可嵌套。例如:

$ echo $(($((5**2)) * 3))

可以简写为:

$ echo $(((5**2) * 3))
$ echo Five divided by two equals $((5/2))

结果为 2。

$ echo with $((5%2)) left over.

结果为 1。

中括号扩展符

示例:

$ echo Front-{A,B,C}-Back

使用逗号分隔字符串或整数或字符列表。且不能包含空格。连续整数的示例:

$ echo Number_{1..5}

连续字母示例:

$ echo {Z..A}

嵌套示例:

$ echo a{A{1,2},B{3,4}}b

输出结果:

aA1b aA2b aB3b aB4b

其最常见的用处是用于列出需要创建的文件和目录列表。例如,如果你要整理你的照片,批量按年月创建目录:

$ mkdir Photos
$ cd Photos
$ mkdir {2007..2009}-0{1..9} {2007..2009}-{10..12}
$ ls

结果如下:

2007-01 2007-07 2008-01 2008-07 2009-01 2009-07
2007-02 2007-08 2008-02 2008-08 2009-02 2009-08
2007-03 2007-09 2008-03 2008-09 2009-03 2009-09
2007-04 2007-10 2008-04 2008-10 2009-04 2009-10
2007-05 2007-11 2008-05 2008-11 2009-05 2009-11
2007-06 2007-12 2008-06 2008-12 2009-06 2009-12

变量扩展符

USER 参数包含你的用户名:

$ echo $USER

查看环境变量列表:

$ printenv | less

如果 $ 符后面的单词不在上面的列表中,那么会输出空字符串,否则会解析变量,输出变量的值。

命令替换

可以使用 $(cmd) 将 cmd 命令的结果作为字符串返回。 示例:

$ echo $(ls)
$ ls -l $(which cp)

输出示例:

-rwxr-xr-x 1 root wheel 29008 3 28 2018 /bin/cp

当命令结果有多行时,会对每行依次执行:

$ file $(ls /usr/bin/* | grep bin/zip)

在旧版本的 shell 中使用反引号代替 $ 符表达式:

$ ls -l `which cp`

引号

示例:

$ echo this is a         test

以上多个空格会压缩为一个空格输出。

$ echo The total is $100.00

以上 $1 会被当作不存在的变量,而输出空字符串输出,最终输出:The total is 00.00

双引号

双引号中的文本中,所有特殊字符都会失去其特殊意义,而被当作普通字符。除了 $\、和反引号是例外。这就意味着分词、路径扩展符、波浪线扩展符和中括号扩展符在双引号中是无效的,但是,变量扩展符、算术扩展符和命令替换仍是有用的。另外,双引号可以用于带空格的文件名。例如,要查看名为 two words.txt 的文件:

$ ls -l two words.txt

结果示例:

ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory

这时,你可以使用双引号来查看该文件并修改文件名:

ls -l "two words.txt"
mv "two words.txt" two_words.txt

仍有效的示例:

$ echo "$USER $((2+2)) $(cal)"

默认情况下,分词会查找空格、TAB 和新行符作为单词分隔符。这就意味着上述字符不会当作文本的一部分。只会当作分隔符。它们将单词分隔为不同的参数,如果使用双引号的话,例如:

$ echo "this is a         test"

那么分词功能就不起作用了,空格就不会被当作分隔符,而是参数的一部分了。 对比以下两个命令的结果:

$ echo $(cal)
$ echo "$(cal)"

第一个命令将 $(cal) 的结果当成了 38 个参数依次输出。第二个命令中 $(cal) 的结果被当作是一个参数,包含空格符和换行符。

单引号

如果你想禁用所有扩展符,使用单引号。对比以下命令的输出:

$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'

从上面例子中可以看出:

  • 不带引号时,所有扩展符可用
  • 带双引号时,$ 符可用,包括命令替换、变量扩展、算术。而 {}~ 不可用。也就是说,除 $ 符相关的扩展符外,其他字符都被当作普通字符串。
  • 带单引号时,所有扩展符皆不可用

转义字符

转义字符使用 \ 反斜杠,主要用于抑制扩展符,例如:

$ echo "The balance for user $USER is: \$5.00"

当文件名中包含 $!& 和空格等 shell 中的特殊字符时,也可以使用转义字符,例如:

$ mv bad\&filename good_filename

如果要对 \ 转义,使用 \\。注意在单引号中,\ 会失去其转义功能,而被当作普通字符。

更多反斜杠技巧

如果你看 man 程序中的文档,你会看到很多 --- 的命令参数:

$ ls -r
$ ls --reverse

为什么有两种类型?一般 - 表示缩写参数,-- 表示完整参数。使用 - 很朦胧,而 -- 更易理解。 如果全部用 -- 形式,那么一个命令就会很长,这时可以使用反斜杠来转义换行符:

$ ls -l \
   --reverse \
   --human-readable \
   --full-time

注意 \ 后面必须是换行符,不能有空格,否则会转义空格,而不是换行符。转义符也可以用于在文本中插入特殊字符。它们称为 反斜杠转义字符。以下是常见的:

转义符 名称 使用场景
\n 新行 在文本中添加空行
\t tab 在文本中添加水平制表符
\a 告警 让终端响铃
\\ 反斜杠 插入一个反斜杠
\f 换页 发送到打印机弹出页面

echo 命令与 -e 选项一起使用:

$ echo -e "Inserting several blank lines\n\n\n"
$ echo -e "Words\tseparated\tby\thorizontal\ttabs."
$ echo -e "\aMy computer went \"beep\"."
$ echo -e "DEL C:\\WIN2K\\LEGACY_OS.EXE"

results matching ""

    No results matching ""