Skip to content

Latest commit

 

History

History
271 lines (214 loc) · 6.96 KB

ModeExpand.md

File metadata and controls

271 lines (214 loc) · 6.96 KB

模式扩展

1. 简介

个人理解,模式扩展就是具有特殊意义的占位符

素材,终端请进入samples文件夹,进行测试。

Shell 接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。 然后 Shell 会扩展词元里面的特殊字符,扩展完成后才会调用相应的命令。

这种特殊字符的扩展,称为模式扩展(globbing) 其中有些用到通配符,又称为通配符扩展(wildcard expansion)

Bash 一共提供八种扩展:

  • ~ 波浪线
  • ? 字符
  • * 字符
  • [] 方括号
  • {} 大括号
  • 变量
  • 子命令
  • 算术

Bash 先进行扩展,再执行命令。因此扩展的结果是由 Bash 负责,与所要执行的命令无关 命令本身并不存在参数扩展,收到什么参数就原样执行

模式扩展与正则表达式的关系使,模式扩展早于正则表达式出现,功能没有正则那么强大,但是简单、方便

允许用户关闭扩展

set -o noglob
# or
set -f

打开扩展

set +o noglob
# or
set +f

2. 波浪线扩展

波浪线 ~ 会自动扩展成当前用户的主目录

echo ~

~user 表示扩展成用户 user 的主目录

echo ~root

~+ 会扩展成当前所在的目录,等同于 pwd 命令。

echo ~+

3. ? 字符扩展

? 字符代表文件路径里面的任意单个字符,不包括空字符。(注意一点:文件系统中可以使用 ? 做为文件名)。

ls ?.txt

4. * 字符扩展

* 字符代表文件路径里面的任意数量的字符串,包括零个字符。

ls *.txt
ls a*.txt
ls *b*

注意,

  • *不会匹配隐藏文件(以 . 开头的文件),只会匹配当前目录
  • Bash 4.0 引入一个参数 globstart,当该参数打开时,允许 ** 匹配零个或多个子目录

5. 方括号扩展

方括号扩展的形式使[...],只有文件确实存在的前提才会扩展。

ls [ab].txt

方括号扩展变体:[!...][^...],表示取反。

ls ?[!a]?

6. [start-end] 扩展

方括号扩展有一个简写形式 [start-end],表示匹配一个连续的范围。 例如 [a-c] 等同于 [abc][0-9] 匹配 [0123456789]。 这部分和正则表达式类似。

常用简写例子:

  • [a-z] 小写字母
  • [A-Z] 大写字母
  • [0-9] 数字

7. 大括号扩展

大括号扩展 {...} 表示分别扩展成大括号里面的所有值,各个值之间使用逗号分隔。比如 {1,2,3} 扩展成 1 2 3。(有点数组的意思)。

echo {1,2,3}
echo d{a,e,i,o,u}g
echo Front-{A,B,C}-Back

大括号可以嵌套。

echo {j{p,pe}g,png}

大括号扩展,总是扩展的,和方括号扩展不同。

touch {d,e,f}.txt

注意,

  • 大括号内部逗号前后不能有空格,否则大括号扩展失效,会被认为是多个参数。
  • 逗号前面可以没值,表示表示该项为空
  • 大括号总是先于其他模式进行扩展

8. {start..end} 扩展

大括号扩展有个简写形式,表示扩展成一个连续序列。 比如 {a..z} 扩展成 26 个小写英文。

echo {a..c}
echo d{a..c}g

这个写法的另一个常见用途,是直接用于 for 循环。

for i in {1..4}
do
  echo $i
done

这种简写形式还可以使用第二个双点号({start..stop..step}),用来指定扩展的步长。

echo {0..8..2}

多个简写形式连用,会有循环处理的效果

echo {a..c}{1..3}

9. 变量扩展

Bash 将美元符号 $ 开头的词元视为变量,将其扩展成变量值。

echo $SHELL

除了放在 $ 后面,也可以放在 ${} 里面

$echo ${SHELL}

10. 子命令扩展

$(...) 可以扩展成另一个命令的运行结果,该命令的所有输出都做为返回值。

echo $(date)
# 另一种古老的写法
echo `date`

$(...) 可以嵌套,比如 $(ls $(pwd))

echo $(ls $(pwd))

11. 算术扩展

$((...)) 可以扩展成整数运算的结果。

echo $((2 + 2))

12. 字符类型

[[:class:]] 表示一个字符类,扩展成某一类的特定字符之中。

常见字符类:

  • [[:alnum:]] 匹配任意英文字母与数字
  • [[:alpha:]] 匹配任意英文字母
  • [[:blank:]] 匹配空格和 Tab 键
  • [[:cntrl:]] ASCII 码 0-31 的不可打印字符
  • [[:print:]] ASCII 码 32-127 可打印字符
  • [[:digit:]] 任意数字,0-9
  • [[:graph:]] A-Z、a-z、0-9 和 标点符号
  • [[:lower:]] 匹配任意小写字母 a-z
  • [[:upper:]] 匹配任意大写字母 A-Z
  • [[:punct:]] 标点符号(除了 A-Z、a-z、0-9 的可打印字符)
  • [[:xdigit:]] 16 进制字符(A-F、a-f 和 0-9)

例子: 打印所有大写字母开头的文件名

echo [[:upper:]]*

字符类的第一个方括号后面,可以加个 !,表示否定

# 输出所有不以数字开头的文件名
echo [![:digit:]]*

13. 使用注意点

  • 通配符是先解释,再执行
  • 文件名扩展在不匹配时,会原样输出
  • 只适用于单层路径,无法跨目录匹配
  • 文件名可以使用通配符

14. 量词语法(zsh 下不支持)

量词语法用来控制模式匹配的次数,它只有在 Bash 的 extglob 参数打开的情况下才能使用,不过一般是默认打开的。

# 查看量词语法开关
shopt extglob

量词语法有下面几种

  • ?(pattern-list) 匹配零个或一个
  • *(pattern-list) 匹配零个或多个
  • +(pattern-list) 匹配一个或多个
  • @(pattern-list) 只匹配一个
  • !(pattern-list) 匹配零个或一个以上的模式,但不匹配单独一个

一些例子

ls abc?(.).xt

15. shopt 命令(zsh 下不支持)

调整 Bash 的行为

# 打开某个参数
shopt -s [optionname]
# 关闭某个参数
shopt -u [optionname]
# 查看某个参数状态
shopt [optionname]