shell命令的扩展和引用

2023-05-16

每次输入命令行按下Enter键时,bash都会在执行命令之前对文本进行多重处理。
首先,我们先提下echo命令,它是shell的一个内置命令,它把文本参数内容打印到标准输出
例如

$ echo this is a test
this is a test

还有个例子

$ echo *
all.txt ls-error.txt ls-output.txt ls.txt test1.txt

这里,并不是输出“*”,而是输出文件夹内所有文件,这是因为“*”意味着“匹配文件名中的任意字符”.

1.扩展

1.1 路径名扩展

通过使用通配符来实现扩展的机制成为路径名扩展(pathname expansion),给定以上主目录,执行下面的扩展:

$ echo l*
ls-error.txt ls-output.txt ls.txt
$ echo *1.txt
test1.txt
$ echo /*/*/lib/
/opt/containerd/lib/ /usr/local/lib/

1.2 波浪线扩展

波浪线(~)用在一个单词的开头,它将被扩展为指定用户的主目录名;如果没有指定用户名,则扩展为当前用户名的主目录.

$ echo ~
/home/lmj

如果指定用户

$ echo ~ksl
/home/ksl

1.3 算术扩展

shell支持通过扩展来运行算术表达式,这允许我们把shell提示符当做计算器来使用。

$ echo $((2+2))
4

语法为

$((expression))

算术扩展只支持整数(没有小数操作),但是可以执行不同的运算,例如加、减、乘、除、取余、取幂.
空格在算术表达式中没有意义,且表达式可以嵌套

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

1.4 花括号扩展

花括号扩展(brace expansion),可以按照花括号里边的模式创建多种文本字符串,例如:

$ echo test-{1,2,3,4}.txt
test-1.txt test-2.txt test-3.txt test-4.txt

用于花括号扩展的模式信息可以包含一个称为前导字符(preamble)的开头部分和一个称为附言(postscript)的结尾部分,花括号表达式本身可以包含一系列逗号分隔的字符串,也可以包含**一系列(两个.)**整数或者单个字符。
例如

$ echo img{1..4}.png
img1.png img2.png img3.png img4.png

或者下面输出一系列逆排序的字母

$ 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

花括号的嵌套,类似于循环的嵌套

$ echo A{1,2}_{3,4}B
A1_3B A1_4B A2_3B A2_4B
$ echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b

1.5 参数扩展

参数扩展(parameter expansion)的许多特性与系统存储小块数据以及给每个小块数据命名的性能有关。例如命名为USER的变量包含了你的用户名。

$ echo $USER
lmj

可以查看可用的变量列表

$ printenv | less

包含了CUDA_HOME,PATH,PWD,HOME等常见的变量。

1.6 命令替换

命令替换可以把一个命令的输出作为一个扩展模式使用,例如

$ echo $(ls)
all.txt ls-error.txt ls-output.txt ls.txt test1.txt
$ ls -l $(which cp)
-rwxr-xr-x 1 root root 151024 Mar  3  2017 /bin/cp

相当于which cp返回/bin/cp,然后再ls -l /bin/cp

2. 引用

现在我们学习如何来控制扩展

$ echo The total is $100.00
The total is 00.00

这跟我们想象中的不同,原因是$1是一个未定义的变量,所以参数扩展把$1的值替换成了空白字符。引用(quoting)机制可以用来有选择性地避免不想要的扩展。

2.1 双引号

第一种引用类型是双引号(double quote).如果文本放在双引号中,那么shell使用的所有特殊字符都将失去它们的特殊含义,而被看做普通的字符。“$”(美元符号),“\”(反斜杠),“’’”(反引号)除外.
一般来说,文件名不允许有空格,加入不幸有个文件名为 two words.txt,可以通过双引号来
阻止单词分割
,得到预期的效果。

$ ls "two words.txt"
$ mv "two words.txt" two_words.txt

但是,参数扩展、算术扩展和命令替换在双引号中仍有效

$ echo "$USER $((2+2)) $(cal)"
lmj 4      June 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

那么双引号对字符替换有什么影响呢?默认情况下,单词分割会先查找是否存在空格、制表符以及换行符,然后把它们当做单次的界定符(delimiter)。这意味着,没有双引号引起来的空格、制表符和换行符都不会被当做文本的一部分,而是被当做分隔符。
例如

$ echo this is a text
this is a text

以上命令行被识别为命令后面跟了四个不同的参数。

$ echo "this is a text"

此时,命令行会被识别为命令后边跟着一个参数“text”

2.2 单引号

如果我们希望抑制所有的扩展,那么应该使用单引号。

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

2.3 转义字符

有时候我们想要引用单个字符,可以通过在该字符前加反斜杠来实现。转义字符经常在双引号中用来有选择性地阻止扩展。

$ echo "The balance for user $USER is \$50.00"
The balance for user lixj is $50.00
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shell命令的扩展和引用 的相关文章

随机推荐