bash之通配符
来源:互联网 发布:网络教育如何考试 编辑:程序博客网 时间:2024/06/05 03:18
为什么要写这篇文章
我相信很多人和我一样,天天在使用linux的shell命令,也大概知道有通配符这么个概念,不过比较模糊。平时也会使用简单的通配符,也许还知道有正则表达式的存在,甚至不清楚两者的区别,往往搞混淆。
我也是同样的问题,从来没有好好地静下心来总结这些东西。其实学习东西还是要踏实,这样才能发挥工具最大的作用,不是吗?本篇文章就shell的通配符来做个总结,方便以后自己查找记忆。注意,这里的shell我指的是bash,因为我几乎就没用过其它的shell,哈哈。
通配符的概念
如果查阅bash的手册或者man文档,我们发现根本压根没有通配符(wildcard)这个字眼,是不是很奇怪呢?进一步查看,转而发现这个通配符概念是路径扩展(英文pathname expansion,或者是文件名扩展(filename expansion))功能中的模式匹配(pattern matching)功能。是不是有点意外呢?
哦,原来在bash中存在很多种形式的扩展(expansion),而路径扩展(或者说文件名扩展)只是其中之一而已,了解这点尤为关键。
那么bash中具体有哪些扩展呢?我们不妨列出来,如下:
- brace expansion (花括号扩展)
- tilde expansion (波浪号扩展)
- parameter and variable expansion (参数和变量扩展)
- arithmetic expansion (算术扩展)
- command substitution (命令置换)
- word splitting (单词分割)
- filename expansion (文件名扩展)
- process substitution(进程替换)
好,本篇文章强调的通配符概念就是文件名扩展中的模式匹配知识点。OK,那么现在我们的问题就转变成了什么是bash的文件名扩展功能?什么是文件名扩展功能中的模式匹配(pattern matching)?bash又是如何处理这些功能的?
很好理解,就是bash在扫描命令行参数(不了解命令行参数的组成部分的童鞋可以参考文章《学会使用getopt函数》)时会注意操作数(Operands)部分是否有*,?,和[这些特殊模式字符(special pattern characters)。当它发现这些特殊模式字符时,会将它们视为要匹配的模式。通俗点说,就是bash发现参数部分有这些特殊字符时,会扩展这些符号,生成相应的已存在的文件名或者目录,最后经过排序后传递给命令。
模式匹配
好了,到这里,我们应该了解到,平时说的所谓通配符在bash中的专业叫法是模式匹配(pattern matching)。
这里顺便提一下,这个模式匹配相比正则表达式而言,那是简单多了,有关正则表达式可以参阅这篇文章《常用正则表达式整理》。
接下来,就让我们详细地了解bash中的特殊模式字符吧。
特殊模式字符以及含义
首先把上图列出的特殊模式字符分为两类:?、*和[set]是最常见的特殊模式字符,在几乎所有的shell中都支持;而后5项是bash的扩展特殊字符,如果想使用,请确保extglob是设置着的,即shopt -s extglob.
好了,接下来结合实际的例子来学些这些特殊模式字符吧!首先是常见的特殊模式字符。
特殊模式字符?匹配任何的单一字符。因此如果目录下有whizprog.c、whizprog.log与whizprog.o这三个文件,那么表达式whizprog.?匹配的结果是whizprog.c和whizprog.o,但是whizprog.log不匹配。
特殊模式字符*是一个功能强大而且广为使用的通配符,它匹配于任何字符组成的字符串(包括空字符串)。表达式whiziprog.*匹配前面提到的三个文件;网页设计人员可以使用*.html表达式匹配他们的所有输入文件。
关于特殊模式字符*,bash有个选项globstar来控制连续两个星号的行为,即出现**的情况:
什么意思呢? 意思就是说选项globstar在disable(shopt -u globstar)情况下,**和*的行为是一样的。但是一旦enable(shopt -s globstar),那么**就会递归匹配所有的文件和目录,而**/仅会递归匹配所有的目录。通过以下实例可以看出实际区别:
[10:06:14@astrol:/etc/systemd]# pwd && ls/etc/systemdjournald.conf logind.conf network resolved.conf system system.conf timesyncd.conf user user.conf[10:06:28@astrol:/etc/systemd]# shopt globstarglobstar off[10:06:36@astrol:/etc/systemd]#[10:06:38@astrol:/etc/systemd]# echo *; echo **journald.conf logind.conf network resolved.conf system system.conf timesyncd.conf user user.confjournald.conf logind.conf network resolved.conf system system.conf timesyncd.conf user user.conf[10:06:46@astrol:/etc/systemd]# echo */; echo **/network/ system/ user/network/ system/ user/[10:06:53@astrol:/etc/systemd]# shopt -s globstar[10:07:00@astrol:/etc/systemd]# echo *; echo **journald.conf logind.conf network resolved.conf system system.conf timesyncd.conf user user.confjournald.conf logind.conf network network/90-mac-for-usb.link network/99-default.link resolved.conf system system/basic.target.wants system/basic.target.wants/live-config.service system/clamav-daemon.service.d system/clamav-daemon.service.d/extend.conf system.conf system/dbus-org.freedesktop.ModemManager1.service system/dbus-org.freedesktop.nm-dispatcher.service system/default.target system/display-manager.service system/getty.target.wants system/getty.target.wants/getty@tty1.service system/graphical.target.wants system/graphical.target.wants/accounts-daemon.service system/hibernate.target.wants system/hibernate.target.wants/anacron-resume.service system/hybrid-sleep.target.wants system/hybrid-sleep.target.wants/anacron-resume.service system/iodined.service system/multi-user.target.wants system/multi-user.target.wants/anacron.service system/multi-user.target.wants/binfmt-support.service system/multi-user.target.wants/console-setup.service system/multi-user.target.wants/cron.service system/multi-user.target.wants/inetd.service system/multi-user.target.wants/irqbalance.service system/multi-user.target.wants/live-tools.service system/multi-user.target.wants/ModemManager.service system/multi-user.target.wants/networking.service system/multi-user.target.wants/NetworkManager.service system/multi-user.target.wants/nmbd.service system/multi-user.target.wants/openbsd-inetd.service system/multi-user.target.wants/pppd-dns.service system/multi-user.target.wants/remote-fs.target system/multi-user.target.wants/rsync.service system/multi-user.target.wants/rsyslog.service system/multi-user.target.wants/smartd.service system/multi-user.target.wants/smbd.service system/multi-user.target.wants/ssh.service system/multi-user.target.wants/vsftpd.service system/network-online.target.wants system/network-online.target.wants/networking.service system/samba-ad-dc.service system/sockets.target.wants system/sockets.target.wants/dm-event.socket system/sockets.target.wants/pcscd.socket system/sockets.target.wants/uuidd.socket system/sshd.service system/suspend.target.wants system/suspend.target.wants/anacron-resume.service system/sysinit.target.wants system/sysinit.target.wants/keyboard-setup.service system/sysinit.target.wants/lvm2-lvmetad.socket system/sysinit.target.wants/lvm2-lvmpolld.socket system/sysinit.target.wants/systemd-timesyncd.service system/syslog.service timesyncd.conf user user.conf[10:07:05@astrol:/etc/systemd]#[10:08:12@astrol:/etc/systemd]# echo */; echo **/network/ system/ user/network/ system/ system/basic.target.wants/ system/clamav-daemon.service.d/ system/getty.target.wants/ system/graphical.target.wants/ system/hibernate.target.wants/ system/hybrid-sleep.target.wants/ system/multi-user.target.wants/ system/network-online.target.wants/ system/sockets.target.wants/ system/suspend.target.wants/ system/sysinit.target.wants/ user/[10:08:23@astrol:/etc/systemd]#
OK,接着看特殊模式字符[set],它与特殊模式字符?很相似,但允许匹配的更确切,把所有想要匹配的字符放在[ ]内,结果匹配其中的任一字符。可以使用波折号-表示范围,也可以使用第一个字符是!或者是^来表示反向匹配。举例如下:
whiziprog.[co]与whizprog.[a-z]匹配文件whizprog.c和whizprog.o,但不匹配文件whizprog.log。
[abc]和[a-c]匹配字符a、b或c
[!0-9]或者[^0-9]匹配任何一个非数字字符
[a-zA-Z0-9_-]匹配任何一个字母、任何一个数字、下划线或者破折号(假设ASCII环境下)。
好了,介绍完了几个常见的特殊模式字符后,我们来看看bash的几个扩展特殊模式字符。使用它们之前,请确保选项extglob是打开的(shopt -s extglob)。
怎么说呢,有了这几个扩展的特殊模式字符,就使得模式匹配有了点正则表达式的味道,自此模式匹配也有了重复、可选的功能了。
注意,这里的pattern-list可以是符号|隔开的模式,表示可选功能。好了,废话不多说,让我们看几个实际例子吧。
(1)列出当前目录下以“ab”或者“def”打头的JPEG或者GIF文件
ls +(ab|def)*.+(jpeg|gif)
(2)列出当前目录下匹配与正则表达式ab(2|3)+\.jpg的所有文件
ls ab+(2|3).jpg
匹配到的文件名诸如ab2.jpg,ab222.jpg,ab3.jpg,ab333.jpg等。
(3)删除当前目录下的jpeg文件或者gif文件,你可能会写出以下表达式:
rm -rf *!(.jpeg|.gif)
但是很遗憾,结果是不对的!这条命令会把当前目录下的所有文件删除。为什么呢?这是因为一开始的星号(*)匹配了所有的文件,当然就包括以.jpeg和.gif为后缀的文件。正确的写法如下:
rm -rf !(*.jpeg|*.gif)
(4)如何列出(1)中的方向结果呢?很简单加个括号在取反就OK!
ls !(+(ab|def)*.+(jpeg|gif))
参考链接:
《bash八大扩展一网打尽》
《shopt nullglob, failglob, extglob, globstar用法》
《Bash Extended Globbing》
- bash之通配符
- bash之通配符
- linux复习笔记 之bash shell (3) 通配符
- bash基础功能之通配符和其他特殊符号
- Bash中的通配符
- bash通配符与特殊符号
- Bash通配符及特殊符号
- bash的通配符
- bash 下的命令行通配符
- linux下bash通配符介绍
- bash通配符和正则表达式
- bash的通配符与特殊符号
- Bash的应用--4.通配符
- bash通配符与组合键
- shell中bash通配符详解
- bash通配符 shell正则表达式
- bash shell元字符(通配符)
- bash中通配符与{}模式的区别
- PAT_Basic 1010
- 《Android开发艺术探索》读书笔记 (4) 第4章 View的工作原理
- uboot 启动流程
- hadoop-2.2.0追加日志记录
- 内存泄漏以及常见的解决方法
- bash之通配符
- C++this指针详解
- int类型定义,float、double类型引用造成的结果
- 编程学习第三天,更多的Python
- C++开源代码项目汇总
- Android ScrollView如何判断上下滑的方向
- spark读取kafka数据 createStream和createDirectStream的区别
- mongdb 基本概念
- 使用SD卡扩展BBB文件系统存储空间