Post

通配符和特殊符号

通配符和特殊符号

首先,以于超老师的的编程经验告诉新人,学通配符,或是正则,请记住

  • 正则、通配符是为了解决某问题
  • 先有问题场景,再琢磨如何写通配符
  • 不要先去写奇怪的通配符或正则,再去琢磨它是什么含义,这是外星人的做法。

什么是通配符

  • 当你在查找特定文件名,却不记得如何拼写时,通配符是帮你寻找的神器。
  • 通配符是专门用于处理文件名的特殊字符,而不是文件内容!
  • 可以方便查找类似、但是不相同的文件名。
  • 通配符是shell的内置语法、大部分linux命令都认识通配符
基本字符通配符模糊匹配的字符内容
yu*yuchao
  yucccc
  yuuuuuuu
  yuddididididi
chao?chaog
  chao1
  chao-
  chao.
  chao_

注意,文件名一般是不带特殊字符的

通配符语法

字符说明示例
*匹配任意字符数。 您可以在字符串中使用星号 (*****)。wh*”将找到 what、white 和 why,但找不到 awhile 或 watch。
?在特定位置中匹配单个字母。b?ll ”可以找到 ball、bell 和 bill。
[ ]匹配方括号中的字符。b[ae]ll”将找到 ball 和 bell,但找不到 bill。
!在方括号中排除字符。b[!ae]ll”将找到 bill 和 bull,但找不到 ball 或 bell。“Like “[!a]*””将找到不以字母 a 开头的所有项目。
-匹配一个范围内的字符。 记住以升序指定字符(A 到 Z,而不是 Z 到 A)。b[a-c]d”将找到 bad、bbd 和 bcd。
   
^同感叹号、在方括号中排除字符b[^ae]ll,找不到ball,找不到bell,能找到bcll
   

* 匹配任意(0或多个)字符串,包括空字符串

? 匹配任意1个字符,且只有一个字符

[abcd] 匹配方括号里的abcd任意一个字符,abcd可以是其他不连续的字符如[aqwd]

[a-z] 匹配方括号里a到z之间的任意一个字符,也可以是连续的数字[1-9]

[!abcd] 不匹配方括号里的任意字符,也可以写为连续的字符,如[!a-z],也就是不匹配a到z任意的一个字符,且!符可以用^替代,写成[^abcd]

1. 练习通配符

1
2
3
[yuchao-linux-242 root /tmp]#mkdir /test ;cd /test
[yuchao-linux-242 root /test]#
[yuchao-linux-242 root /test]#touch yuchao.txt yuc.txt cc.txt yuchao01.log yuyu.log cc.sh

* 匹配任意字符

Asterisk

找出所有txt结尾的文件

1
2
[yuchao-linux-242 root /test]#ls *.txt
cc.txt  yuchao.txt  yuc.txt

查看以sh结尾的文件

1
2
[yuchao-linux-242 root /test]#ls *.sh
cc.sh

查看以yu开头、txt结尾的文件

1
2
[yuchao-linux-242 root /test]#ls yu*.txt
yuchao.txt  yuc.txt

查看以yu开头、log结尾的文件

1
2
[yuchao-linux-242 root /test]#ls yu*.log
yuchao01.log  yuyu.log

查看所有以yu开头的文件

1
2
[yuchao-linux-242 root /test]#ls yu*
yuchao01.log  yuchao.txt  yuc.txt  yuyu.log

找出以c开头的文件

1
2
[yuchao-linux-242 root /test]#ls c*
cc.sh  cc.txt

? 匹配任意一个字符(用得少)

1
2
[yuchao-linux-242 root /test]#ls ?.sh
ls: cannot access ?.sh: No such file or directory

这个报错了,为什么?因为没有一个文件叫做 ?.sh

除非你去创建一个

1
2
3
[yuchao-linux-242 root /test]#touch c.sh
[yuchao-linux-242 root /test]#ls ?.sh
c.sh

所以,作用不大,只用于特定场景。

如何查找特定字符数量的文件? 比如找出sh脚本文件

1
2
[yuchao-linux-242 root /test]#ls *.sh
cc.sh  c.sh

你只能多写几个问号

1
2
3
4
5
[yuchao-linux-242 root /test]#ls ?.sh
c.sh
[yuchao-linux-242 root /test]#
[yuchao-linux-242 root /test]#ls ??.sh
cc.sh

再比如找出所有txt

1
2
3
4
5
6
7
[yuchao-linux-242 root /test]#ls ??.txt
cc.txt
[yuchao-linux-242 root /test]#ls ??????.txt
yuchao.txt
[yuchao-linux-242 root /test]#
[yuchao-linux-242 root /test]#ls ???.txt
yuc.txt

[] 匹配方括号里的内容

创建测试数据,如

1
2
3
4
[yuchao-linux-242 root /test]#touch {a..g}.log
[yuchao-linux-242 root /test]#ls
a.log  b.log  cc.sh  cc.txt  c.log  c.sh  d.log  e.log  f.log  g.log  yuchao01.log  yuchao.txt  yuc.txt  yuyu.log
[yuchao-linux-242 root /test]#

找出文件名是a-z之间任意一个字符的txt

1
2
[yuchao-linux-242 root /test]#ls [a-z].txt
ls: cannot access [a-z].txt: No such file or directory

报错了,因为没有

找出a-z之间任意一个字符的log

1
2
[yuchao-linux-242 root /test]#ls [a-z].log
a.log  b.log  c.log  d.log  e.log  f.log  g.log

找出a-c之间任意一个字符的log

1
2
[yuchao-linux-242 root /test]#ls [a-c].log
a.log  b.log  c.log

创建测试数据

1
2
3
4
5
6
7
[yuchao-linux-242 root /test]#touch yu{1..5}.log
[yuchao-linux-242 root /test]#touch yc{1..5}.log
[yuchao-linux-242 root /test]#
[yuchao-linux-242 root /test]#ls
a.log  cc.sh   c.log  d.log  f.log  yc1.log  yc3.log  yc5.log  yu2.log  yu4.log  yuchao01.log  yuc.txt
b.log  cc.txt  c.sh   e.log  g.log  yc2.log  yc4.log  yu1.log  yu3.log  yu5.log  yuchao.txt    yuyu.log
[yuchao-linux-242 root /test]#

找出以yu1 yu2 yu3 相关的log文件

1
2
[yuchao-linux-242 root /test]#ls yu[1-3].log
yu1.log  yu2.log  yu3.log

找出以y开头相关的log

1
2
[yuchao-linux-242 root /test]#ls y*.log
yc1.log  yc2.log  yc3.log  yc4.log  yc5.log  yu1.log  yu2.log  yu3.log  yu4.log  yu5.log  yuchao01.log  yuyu.log

只找出文件名是三个字母的log文件

1
2
3
[yuchao-linux-242 root /test]#ls [a-z][a-z][a-z0-9].log
yc1.log  yc2.log  yc3.log  yc4.log  yc5.log  yu1.log  yu2.log  yu3.log  yu4.log  yu5.log
[yuchao-linux-242 root /test]#

[!abcd] 取反方括号的内容

1
2
3
[yuchao-linux-242 root /test]#ls
a.log  cc.sh   c.log  d.log  f.log  yc1.log  yc3.log  yc5.log  yu2.log  yu4.log  yuchao01.log  yuc.txt
b.log  cc.txt  c.sh   e.log  g.log  yc2.log  yc4.log  yu1.log  yu3.log  yu5.log  yuchao.txt    yuyu.log

找出除了以abcd开头的log文件

1
2
[yuchao-linux-242 root /test]#ls [!abcd]*.log
e.log  f.log  g.log  yc1.log  yc2.log  yc3.log  yc4.log  yc5.log  yu1.log  yu2.log  yu3.log  yu4.log  yu5.log  yuchao01.log  yuyu.log

作用同上,必须是连续的数字

1
[yuchao-linux-242 root /test]#ls [!a-d]*.log

找出除了abcd开头的单个字母的log文件

1
2
[yuchao-linux-242 root /test]#ls [!abcd].log
e.log  f.log  g.log

排除所有名字里包含y和u的文件

1
2
[yuchao-linux-242 root /test]#ls [!yu]*
a.log  b.log  cc.sh  cc.txt  c.log  c.sh  d.log  e.log  f.log  g.log

排除所有名字里包含y和u的sh文件

1
2
[yuchao-linux-242 root /test]#ls [!yu]*.sh
cc.sh  c.sh

2.通配符 find 综合练习

搜索/etc下所有包含hosts相关字符的文件

1
2
3
4
[lamp-server root ~]$find /etc/ -type f -name '*hosts*'
/etc/hosts
/etc/hosts.allow
/etc/hosts.deny

搜索/etc下的以ifcfg开头的文件(网卡配置文件)

1
2
3
[lamp-server root ~]$find /etc/ -type f -name 'ifcfg*'
/etc/sysconfig/network-scripts/ifcfg-lo
/etc/sysconfig/network-scripts/ifcfg-ens33

只查找以数字结尾的网卡配置文件

1
2
[lamp-server root ~]$find /etc/ -type f -name 'ifcfg*[0-9]'
/etc/sysconfig/network-scripts/ifcfg-ens33

找到系统中的第一块到第四块磁盘,注意磁盘的语法命名

1
2
3
4
5
[yuchao-linux01 root ~]$find /dev -name  'sd[a-d]'
/dev/sdd
/dev/sdc
/dev/sdb
/dev/sda

找找sdb硬盘有几个分区,多种写法

1
2
3
4
5
[yuchao-linux01 root ~]$ls /dev/sdb?
/dev/sdb1  /dev/sdb2  /dev/sdb3  /dev/sdb4  /dev/sdb5  /dev/sdb6  /dev/sdb7

[yuchao-linux01 root ~]$ls /dev/sdb[0-9]
/dev/sdb1  /dev/sdb2  /dev/sdb3  /dev/sdb4  /dev/sdb5  /dev/sdb6  /dev/sdb7

注意*是和上面不同的

1
2
[yuchao-linux01 root ~]$ls /dev/sdb*
/dev/sdb  /dev/sdb1  /dev/sdb2  /dev/sdb3  /dev/sdb4  /dev/sdb5  /dev/sdb6  /dev/sdb7

通配符练习二

测试数据源准备

1
2
3
4
5
[yuchao-linux01 root ~/test_shell]$touch {a..h}.log
[yuchao-linux01 root ~/test_shell]$touch {1..10}.txt
[yuchao-linux01 root ~/test_shell]$ls
10.txt  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt  a.log  b.log  c.log  d.log  e.log  f.log  g.log  h.log
[yuchao-linux01 root ~/test_shell]$

找出a到e的log文件

1
2
[yuchao-linux01 root ~/test_shell]$ls [a-e].log
a.log  b.log  c.log  d.log  e.log

找出除了3到5的txt文件

1
2
[yuchao-linux01 root ~/test_shell]$ls [!3-5].txt
1.txt  2.txt  6.txt  7.txt  8.txt  9.txt

找出除了2,5,8,9的txt文件

1
2
[yuchao-linux01 root ~/test_shell]$ls [!2,5,8,9].txt
1.txt  3.txt  4.txt  6.txt  7.txt

同理写法

1
2
[yuchao-linux01 root ~/test_shell]$ls [^2,5,8,9].txt
1.txt  3.txt  4.txt  6.txt  7.txt

找出除了a,e,f的log文件

1
2
[yuchao-linux01 root ~/test_shell]$ls [!a,e,f].log
b.log  c.log  d.log  g.log  h.log

同理写法

1
2
[yuchao-linux01 root ~/test_shell]$ls [^a,e,f].log
b.log  c.log  d.log  g.log  h.log

3.特殊符号

什么是特殊符号

比起通配符来说,linux的特殊符号更加杂乱无章,但是一个专业的linux运维

孰能生巧,这些都不是问题

路径相关

符号作用
~当前登录用户的家目录
-上一次工作路径
.当前工作路径,或表示隐藏文件 .yuchao.linux
..上一级目录

引号相关

1
2
3
4
'' 单引号、所见即所得
"" 双引号、可以解析变量及引用命令
`` 反引号、可以解析命令
   无引号,一般我们都省略了双引号去写linux命令,但是会有歧义,比如空格,建议写引号

重定向符号

1
2
3
4
5
6
7
>          stdout覆盖重定向
>>         stdout追加重定向

<            stdin重定向

2>   stderr重定向
2>>  stderr追加重定向

命令执行

1
2
3
4
5
6
7
8
command1 && command2      #  command1成功后执行command2
command1 || command2      #  command1失败后执行command2
command1 ; command2         #  无论command1成功还是失败、后执行command2
\                # 转义特殊字符,还原字符原本含义
$()            # 执行小括号里的命令
``     # 反引号,和$()作用一样
|             # 管道符
{}         # 生成序列

4.引号练习

单引号

例如使用date练习

单引号是无法识别date命令的

1
2
3
4
5
6
7
[yuchao-linux01 root ~/test_shell]$date
Sat Apr  2 17:06:01 CST 2022
[yuchao-linux01 root ~/test_shell]$
[yuchao-linux01 root ~/test_shell]$echo 'date'
date
[yuchao-linux01 root ~/test_shell]$echo '$(date)'
$(date)

结论、单引号是所见即所得,单引号里面是什么,输入就是什么,没有任何改变,特殊符号也都失去了其他作用。

反引号

反引号中的linux命令是可以执行的,且反引号中只能写可执行的命令

1
2
3
4
5
6
7
8
9
10
11
12
# 依然是date命令

[yuchao-linux01 root ~/test_shell]$date
Sat Apr  2 17:32:56 CST 2022
[yuchao-linux01 root ~/test_shell]$
[yuchao-linux01 root ~/test_shell]$echo `date`
Sat Apr 2 17:32:59 CST 2022
[yuchao-linux01 root ~/test_shell]$echo `pwd`
/root/test_shell

[yuchao-linux01 root ~/test_shell]$echo "于超老师的外号是`echo 超哥`"
于超老师的外号是超哥

总结

系统会首先执行反引号里的命令,然后再进行下一步的处理。

双引号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[yuchao-linux01 root ~/test_shell]$echo "date"
date
[yuchao-linux01 root ~/test_shell]$echo "`date`"
Sat Apr  2 17:39:52 CST 2022
[yuchao-linux01 root ~/test_shell]$
[yuchao-linux01 root ~/test_shell]$echo "$PATH"
/opt/jdk/BIN:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/bin:/opt/jdk/bin:/root/bin
[yuchao-linux01 root ~/test_shell]$

[yuchao-linux01 root ~/test_shell]$name="超哥"
[yuchao-linux01 root ~/test_shell]$
[yuchao-linux01 root ~/test_shell]$echo "于超老师的外号是$name"
于超老师的外号是超哥

[yuchao-linux01 root ~/test_shell]$echo "于超老师的外号是$name,当前的linux工作路径是$PWD"
于超老师的外号是超哥,当前的linux工作路径是/root/test_shell

结论

当输出双引号内的内容是,如果内容里有linux命令、或者变量、特殊转义符等

会优先解析变量、命令、转义字符,然后得到最终的内容

无引号

没有引号、很难确定字符串的边界,很容易出现各种故障

1
2
3
4
5
6
7
8
9
10
11
12
[yuchao-linux01 root ~/test_shell]$echo 于超老师的外号是 $name
于超老师的外号是 超哥

[yuchao-linux01 root ~/test_shell]$echo 于超老师的外号是 $name 当前的工作路径是 $PWD
于超老师的外号是 超哥 当前的工作路径是 /root/test_shell

[yuchao-linux01 root ~/test_shell]$echo "于超老师的外号是 $name 当前的工作路径是 $PWD"
于超老师的外号是 超哥 当前的工作路径是 /root/test_shell


[yuchao-linux01 root ~/test_shell]$echo '于超老师的外号是 $name 当前的工作路径是 $PWD'
于超老师的外号是 $name 当前的工作路径是 $PWD

5.特殊符号练习

重定向符号

之前讲过重定向符号、以及数据流的结合用,这里就不重复了。

; 分号

  • 表示命令的结束
  • 多个命令之间的分隔符
  • 某些配置文件的注释符
1
2
3
4
[yuchao-linux01 root ~/test_shell]$pwd;mkdir hehe;cd hehe;pwd
/root/test_shell
/root/test_shell/hehe
[yuchao-linux01 root ~/test_shell/hehe]$

# 符

注释符号 如命令的注释

1
2
3
[yuchao-linux01 root ~/test_shell/hehe]$# hello super man
[yuchao-linux01 root ~/test_shell/hehe]$
[yuchao-linux01 root ~/test_shell/hehe]$# ls /opt

如配置文件的注释符

1
2
3
4
5
6
7
8
9
10
# nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

| 管道符

如生活中的管道,能够传输物质

Linux管道符用于传输数据,对linux命令的处理结果再次处理,直到得到最终结果
1
2
3
4
5
6
7
8
9
10
[yuchao-linux01 root ~/test_shell/hehe]$ifconfig |grep inet
        inet 192.168.0.240  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::4913:8ad0:3a1:c439  prefixlen 64  scopeid 0x20<link>
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>


[yuchao-linux01 root ~/test_shell/hehe]$netstat -tunlp|grep ssh
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1063/sshd
tcp6       0      0 :::22                   :::*                    LISTEN      1063/sshd

能一次出结果的命令,尽量不要二次加工,效率并不高

&& 符

创建目录成功后,才执行后面的命令

1
2
3
4
5
[yuchao-linux01 root ~/test_shell/hehe]$mkdir /chaoge_data && cd /chaoge_data
[yuchao-linux01 root /chaoge_data]$
[yuchao-linux01 root /chaoge_data]$
[yuchao-linux01 root /chaoge_data]$mkdir /chaoge_data && cd /chaoge_data
mkdir: cannot create directory ‘/chaoge_data’: File exists

如果前面命令失败,后面命令不执行

1
2
[yuchao-linux01 root /chaoge_data]$mkdir /chaoge_data && pwd
mkdir: cannot create directory ‘/chaoge_data’: File exists

只有前面成功,后面才执行

1
2
[yuchao-linux01 root /chaoge_data]$mkdir /chaoge_data2 && pwd
/chaoge_data

|| 符

只有前面命令失败、才执行后面命令

1
2
3
[yuchao-linux01 root /chaoge_data]$mkdir /chaoge_data ||  pwd
mkdir: cannot create directory ‘/chaoge_data’: File exists
/chaoge_data

前面成功了,后面不执行

1
[yuchao-linux01 root /chaoge_data]$mkdir /chaoge_data222 ||  pwd

$() 符

引用系统时间,创建文件名,脚本常见做法

1
2
3
4
5
[yuchao-linux01 root /chaoge_data]$touch nginx_access_$(date +%F).log
[yuchao-linux01 root /chaoge_data]$
[yuchao-linux01 root /chaoge_data]$ll
total 0
-rw-r--r-- 1 root root 0 Apr  2 18:03 nginx_access_2022-04-02.log

找到当前的txt文件,然后删掉

1
[yuchao-linux01 root ~/test_shell]$rm -f $(find . -name '*.txt')

等同写法

1
[yuchao-linux01 root ~/test_shell]$rm -f `find . -name '*.log'`

{} 符

生成连续的数字序列

1
2
[yuchao-linux01 root ~/test_shell]$echo {1..30}
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
[yuchao-linux01 root ~/test_shell]$echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z

特殊用法,拷贝文件的简写

1
2
3
[yuchao-linux01 root ~/test_shell]$ll /etc/sysconfig/network-scripts/ifcfg-ens33*
-rw------- 1 root root 408 Mar 19 14:59 /etc/sysconfig/network-scripts/ifcfg-ens33
-rw-r--r-- 1 root root 408 Apr  2 18:17 /etc/sysconfig/network-scripts/ifcfg-ens33.bak

作为变量的分隔符

1
2
3
4
[yuchao-linux01 root ~/test_shell]$touch ${name}_`date +%F`.log
[yuchao-linux01 root ~/test_shell]$ll
total 0
-rw-r--r-- 1 root root 0 Apr  2 18:18 超哥_2022-04-02.log
This post is licensed under CC BY 4.0 by the author.