《快乐的 Linux 命令行》
字符展开
1 2
| $ echo * anaconda-ks.cfg certbot-auto ls-output.txt uniq-test
|
shell
在echo
命令被执行前把*
展开成了另外的东西。
当回车键被按下时,shell
在命令被执行前在命令行上自动展开任何符合条件的字符,所以echo
命令的实际参数并不是*
,而是它展开后的结果
。
路径名展开
通配符所依赖的工作机制叫做路径名展开
。
1 2
| $ echo D* Desktop Documents Downloads
|
1 2
| $ echo *s Applications Documents Downloads Movies Pictures sensors
|
1 2
| $ echo [[:upper:]]* Applications Desktop Documents Downloads Library Movies Music Pictures Postman Public
|
1 2
| $ echo /usr/*/share /usr/local/share
|
以圆点字符开头的文件名是隐藏文件,路径名展开也尊重这种行为,echo *
不会显示隐藏文件。
~
当它用在一个单词的开头时,它会展开成指定用户的家目录名,如果没有指定用户名,则展开成当前用户的家目录:
如果有用户foo
这个帐号,那么:
算术表达式展开
shell
在展开中执行算数表达式,这允许我们把shell
提示当作计算器来使用:
算术表达式只支持整数。
然而我好像用了不是整数的数,也算出来结果了,可能和Linux
版本有关系:
1 2
| $ echo $((5.2423/2)) 2.6211500000000001
|
支持的运算符:+
-
*
/
%
**
。
因为只支持整数,所以除法的结果也是整数
。
在算术表达式中空格并不重要,并且表达式可以嵌套。
1 2
| $ echo $(($((5**2)) * 3)) 75
|
花括号展开
可以从一个包含花括号的模式中创建多个文本字符串。
1 2
| $ echo Front-{A,B,C}-Back Front-A-Back Front-B-Back Front-C-Back
|
花括号展开模式可能包含一个开头部分叫做报头
,一个结尾部分叫做附言
。
花括号表达式
本身可能包含一个由逗号分开的字符串列表
,或者一个整数区间
,或者单个的字符的区间
。
这种模式不能嵌入空白字符。
1 2
| $ echo Number_{1..5} Number_1 Number_2 Number_3 Number_4 Number_5
|
1 2
| $ echo {Z..A} Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
|
花括号展开可以嵌套:
1 2
| $ echo a{A{1,2},B{3,4}}b aA1b aA2b aB3b aB4b
|
还有一些参数变量
展开:
但在参数展开中,如果你拼写错了一个变量名,展开仍然会进行,只是展开的结果是一个空字符串:
命令替换
命令替换允许我们把一个命令的输出作为一个展开模式来使用:
1 2
| $ echo $(ls) Applications Desktop Documents Downloads Library Movies Music Pictures Postman Public go node sensors
|
1 2
| $ ls -l $(which cp) -rwxr-xr-x 1 root wheel 42272 May 28 07:37 /bin/cp
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $ file $(ls /usr/bin/* | grep zip) /usr/bin/bunzip2: Mach-O 64-bit executable x86_64 /usr/bin/bzip2: Mach-O 64-bit executable x86_64 /usr/bin/bzip2recover: Mach-O 64-bit executable x86_64 /usr/bin/funzip: Mach-O 64-bit executable x86_64 /usr/bin/gunzip: Mach-O 64-bit executable x86_64 /usr/bin/gzip: Mach-O 64-bit executable x86_64 /usr/bin/unzip: Mach-O 64-bit executable x86_64 /usr/bin/unzipsfx: Mach-O 64-bit executable x86_64 /usr/bin/zip: Mach-O 64-bit executable x86_64 /usr/bin/zipcloak: Mach-O 64-bit executable x86_64 /usr/bin/zipdetails: Perl script text executable /usr/bin/zipdetails5.18: Perl script text executable /usr/bin/zipdetails5.28: Perl script text executable /usr/bin/zipgrep: POSIX shell script text executable, ASCII text /usr/bin/zipinfo: Mach-O 64-bit executable x86_64 /usr/bin/zipnote: Mach-O 64-bit executable x86_64 /usr/bin/zipsplit: Mach-O 64-bit executable x86_64
|
在旧版shell
程序中,有另一种语法也支持命令替换,使用倒引号
来代替美元符号和括号:
1 2
| $ ls -l `which cp` -rwxr-xr-x 1 root wheel 42272 May 28 07:37 /bin/cp
|
引用
用双引号
包裹的字符串,单词分割
、路径名展开
、波浪线展开
和花括号展开
会失效,参数展开
、 算术展开
和命令替换
仍然执行。
1 2 3 4 5 6 7 8
| $ echo "$USER $((2+2)) $(cal)" onns 4 November 2020 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
例外的是$
\
`
。
在默认情况下,单词分割机制会在单词中寻找空格
,制表符
,和换行符
,并把它们看作单词之间的界定符。这意味着无引用的空格,制表符和换行符都不是文本的一部分,它们只作为分隔符
使用。
虽然命令替换还有效果,但是有时候可能会有用:
1 2 3 4 5 6 7 8 9 10
| $ echo $(cal) November 2020 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ echo "$(cal)" November 2020 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
如果需要禁止所有的展开,我们要使用单引号
。
1 2
| $ echo '$USER $((2+2)) $(cal)' $USER $((2+2)) $(cal)
|
也可以用单个的转义字符反斜杠\
。
注意在单引号中,反斜杠失去它的特殊含义,它被看作普通字符。