07-1透过shell看世界——扩展

时间:2022-07-22
本文章向大家介绍07-1透过shell看世界——扩展,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本章,将介绍在按下 Enter 键时,命令行中发生的一些神奇事情。将使用 echo 这一新命令来处理。

  • echo: 显示一行文本。

一、扩展

每次输入命令行按下 Enter 键时,bash 都会在执行命令之前对文本进行多重处理。 之前见过,一个简单的字符序列(比如 * )在shell 中被识别为多种意思的例子。产生这个结果的处理过程称为扩展。 有了扩展功能,在输入内容后,这些内容将在 shell 对其执行之前被扩展成其他内容。为了证明这点,让我们先来看看 echo 命令。

0.echo-显示一行文本

echo 是 shell 的一个内置命令,它执行的任务很简单,把文本参数内容打印到标准输出

(1)用法格式

echo 文本
'''
    功能:把文本参数内容打印到标准输出。
    参数:
        ① 文本:传递给 echo 的任何参数都将显示出来。
            
    选项:
        ① -n: 不换行输出(不添加 -n 选项,文本输出后指定换行;添加后文本直接跟着输出并无换行)。
        ② -e: 输出转义字符。
            常用的转义字符如下:
                b: 转义后相当于按退格键(backspace) ,但前提是"b"后面存在字符,具体效果参考下方示例。

                c: 不换行输出,在"c"后面不存在字符的情况下,作用相当于echo -n,具体效果参考下方示例。

                n: 换行,效果看示例。

                f: 换行,但是换行后的新行的开头位置连接着上一行的行尾,具体效果查看示例;

                v: 与f相同;

                t: 转以后表示插入tab,即制表符,已经在上面举过例子;

                r: 光标移至行首,但不换行,相当于使用"r"以后的字符覆盖"r"之前同等长度的字符,只看
                    这段文字描述的话可能不容易理解,具体效果查看示例;

                \: 表示插入""本身;
        
    
    返回值:文本参数内容。
'''
示例
① 不添加选项
echo this is a test

echo 123

echo "www.xiansiqi.net"

传递给 echo 的任何参数都将显示出来

echo *
# 输出的却不是 * ,这是为什么?

回忆下之前对通配符的使用。 “ * ”字符意味着“ 匹配文件名中的任意字符 ”。 shell 会在执行 echo 命令前把“ * ” 字符扩展成其它内容(在这个例子中,会扩展为当前工作目录下的所有文件名)。 在按下 Enter 键时,shell 会在执行命令前自动扩展命令行中所有符合条件的字符,因此 echo 命令将不可能看到“ * ”字符,只能看到“ * ”字符扩展后的结果。

② -n 选项不换行

在这里同时echo两条信息效果比较明显,通过使用分号来分隔多条命令,就可以将多条命令输入在一行中(command1;command2;command3...)。

echo "www.xiansiqi.net" ; echo "www.wm99.net"
# 未添加 -n 选项,2条命令,输出后指定换行


echo -n "www.xiansiqi.net" ; echo "www.wm99.net"
# 添加 -n 选项,2条命令,输出后不换行
③ -e 选项输出转义字符

使用 echo -e 输出转义字符,将转义后的内容输出到屏幕上。

echo -e "www.xiansiqi.nettNeverGiveUp!"
# 在这里使用了t制表符,输出结果为转义后的内容,所以我们只要能够记住这些转义字符,就可以在echo命令中
   输出它们。



echo -e "123b"
echo -e "123b456"
echo -e "123bb456"
echo -e "123bbb456"
#使用echo命令输出"b"转义字符,在"b"后面存在字符的前提下,"b"表示删除前一个字符,"bb"表示删除
前两个字符,依此类推。从输出结果可以看到,上例中,在"b"后面不存在任何字符时,"b"并没有转义为"退格键",
当"b"后面存在字符时,一个"b"就相当于按一次backspace键。


echo -e "abcc"
echo -n "abc"
echo -e "abccdef"
echo -e "abcndef"
# 也可以使用c转义符,表示**不换行输出**,但是当"c"后面仍然存在字符时,"c"后面的字符将不会被输出,
如果"c"后面不存在任何字符时,效果与使用"echo -n"相同。"n"转义后表示换行,最后1例中,被输出的字符
从"n"处开始另起一行。


echo -e "123f456"
echo -e "abcf456f520"
# "f"转移符表示换行,但是换行后的新行的开头位置连接着上一行的行尾,第2个例子中有两个"f"。


echo -e "12345rabc"
echo -e "123rabc"
echo -e "1rabc"
echo -e "12r"
# "r"转义符表示使用"r"后面的字符覆盖"r"之前的同等长度的字符,比较不容易理解,但是以上示例,
就很容易明白了。上图中的第一个示例中,"r"后面的abc覆盖了123,45没有被覆盖;
第二个示例中,因为abc一共有3个字符,123也是有3个字符,所以abc覆盖了123以后,只剩下了abc;
第三个示例中,1只有一个字符,覆盖以后只剩下abc;第四个示例中,"r"后面并不存在任何字符,所以"r"前面
的字符没有被覆盖。


echo -e "abc\123"
# "\"经过转义以后,表示""
④ 结果格式变化

当使用 echo 输出命令替换后的内容时,命令执行结果的格式可能会发生变化。 比如,如果我们想要输出 ifconfig 命令执行后的结果,我们可能会使用如下命令:

echo 'ifconfig'

但是我们发现,这样输出的文本的格式发生了变化,这样可能不是我们想要的,因为当我们直接执行 ifconfig 命令时,ifconfig 返回的结果是多行的,可是当我们使用 echo 输出的时候,格式发生了变化,如果想要按照命令执行后的原格式输出命令替换后的结果,可以使用如下方法,如下方法在写脚本的时候可能会用到

echo "'ifconfig'"

1.路径名扩展

(1)是什么?

通过使用通配符来实现扩展的机制称为路径名扩展。 试试在之前章节使用过的一些技术,将会发现它们实际上就是扩展。

① 示例
#先给定一个主目录

ls
# 查看当前工作目录的所有文件和子目录

echo D*
# 以 D 开头的所有文件

echo *s
# 以 s 结尾的所有文件

echo [[:upper:]]*
# 以大写字母开头的所有文件

echo /usr/*/share
# 查看除主目录之外的目录

(2)隐藏文件的路径名扩展

众所周知,文件名以一个“ . ”点字符开头的文件都将被隐藏。路径名扩展功能也遵循这个规则,类似 echo * 这样的扩展并不能显示隐藏的文件。

2.波浪线扩展

复习之前对 cd 命令的介绍,如 cd~username 会将工作目录改变为 username 的主目录。你会发现波浪线字符(~)具有特殊含义。 如果把它(~)用在一个单词的开头,那么它将被扩展为指定用户的主目录名;如果没有指定用户命名,那么将扩展为当前用户的主目录

(1)指定用户

echo ~foo

# 如果有 foo 这个用户

(2)未指定用户

echo ~

3.算术扩展

shell 支持通过扩展来运行算术表达式。这使得我们可以把 shell 提示符当作计算器。 算术扩展只支持整数(全是数字,没有小数),但可以执行很多不同的运算。 空格在算术表达式中是没有意义的,而且表达式是可以嵌套的

(1)用法格式

$((expression))
/*
    功能:算术扩展来运行算术表达式.
    参数:
        ① expression: 包含数值和算术操作符的算术表达式。(只支持整数)
        
    返回值: 运算后的结果。
*/
① 算术运算符

算术扩展支持的操作符。

运算符

描述

-

*

/

除(切记:因为算术扩展只支持整数运算,所以结果也是整数)

%

取余,即余数

**

取幂

(2)空格无意义

空格在算术表达式中是没有意义的

echo $((2 + 2))
# 进行 2 + 2 运算,注意我添加了空格,没有影响,这是因为空格在算术表达式中是没有意义的

(3)表达式可嵌套

表达式是可以嵌套的。

示例

把 5^2 和 3 相乘。

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

(4)使用一对括号组合多个子表达式

可以使用一对括号来组合多个子表达式。通过该技术,可以把上面的例子重写,用一个扩展来代替两个,可得同样结果:

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

(5)除、取余运算

注意整数相除的结果。

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


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

4.花括号扩展

使用它,你可以按照花括号里面的模式创建多种文本字符串。 用于花括号扩展的模式信息可以包含 一个称为前导字符的开头部分 和 一个称为附言结尾部分。 花括号表达式本身可以包含一系列逗号分隔的字符串,也可以包含一系列整数 或 单个字符。 切记:模式信息不能包含内嵌空白

(1)用法格式

# 包含一系列逗号分隔的字符串
{1,2}

# 包含一系列整数 或 单个字符
{1..5}  # 一系列整数
{a..b}  # 一系列单个字符
① 一系列整数
echo Number—{1..5}
② 一系列单个字符
echo {Z..A}
③ 一系列逗号分隔的字符串
echo {a,b,c}
④ 嵌套
echo a{A{1,2},B{3,4}}b

(2)应用

最普遍的应用是创建一系列的文件或者目录。 比如,摄影师有一个很大的图片集,想要按年份、月份来对这些图片进行分组,那么要做的第一件事就是创建一系列以年月格式命名的目录。这样,这些目录名将会按照年代顺序排列,输出目录的一个完整列表。但是这样做工作量大、易出错。所以我们这样操作:

mkdir Pics

cd Pics

mkdir {2009..2011}-0{1..9} {2009..2011}-{10..12}

ls

5.参数扩展

参数扩展用在 shell 脚本中比直接用在命令行中更有用它的许多特性与系统存储小块数据以及给每个小块数据命名的性能有关。很多这样的小块数据(称为变量会更合适)可用于扩展

(1)用法格式

$变量名
示例

例如:命名为 USER 的变量包含你的用户名,为了触发参数扩展,并显示出 USER 的内容,可进行如下操作:

echo $USER

(2)查看可用的变量列表

想查看可用的变量列表,进行如下操作:

printenv | less

(3)输入错误仍扩展

对于其它的扩展类型来说,如果误输入了一个模式,就不会发生扩展,而这时 echo 命令只是显示这些误输入的模式信息,但是对于参数扩展来说,如果变量名拼写错误,仍然会进行扩展,只不过结果输出的是一个空字符而已。

示例
echo $SUER

# 拼写错误

6.命令替换

(1)是什么?

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

echo $(ls)

ls -l $(which cp)
# 这里,把 which cp 命令的运行结果作为 ls 命令的一个参数,因此我们无需知道 cp 程序所在的完整路径
就能获得 cp 程序对应的列表,这个功能并不只是局限于简单的命令,也可以应用于整个管道中
(只不过只显示部分输出内容)。

(2)语法格式

$(命令)
示例
file $(ls /usr/bin/* | grep zip)

# 此例子中,管道的输出未 file 命令的参数列表。

在早期的 shell 程序中,存在命令替换的另一种语法格式,bash 也支持这种格式。 它用反引号代替美元符号和括号,具体如下所示:

ls -l `which cp`