Linux的系统符号与正则表达式
1 Linux系统符号
在Linux中,符号都有一些各自的含义和作用,并且可以跟一些命令进行组合使用。
1.1 通配符符号
在Linux有两种通配符符号,分别是 *
和 { }
。
{}
符号:可以用来生成序列。比如:
# 生成序列
[root@web syushin]# echo {a..e}
a b c d e
[root@web syushin]# echo {A..E}
A B C D E
[root@web syushin]# echo {1..5}
1 2 3 4 5
# 指定间隔序列,{开始..结束..间隔}
[root@web syushin]# echo {1..10..2}
1 3 5 7 9
常见的用法:批量创建文件和备份单个文件
[root@web syushin]# touch {a..d}.txt
[root@web syushin]# ls
a.txt b.txt c.txt d.txt
# 备份一个文件
[root@web syushin]# cp a.txt{,.bak}
[root@web syushin]# ls
a.txt a.txt.bak
*
符号:在日常运维中非常常用,在文件扩展名上,它用来表示任意一个字符,
[root@web syushin]# ls
abc adc aec
[root@web syushin]# ls a*c
abc adc aec
在运算时,它表示乘法:
[root@web syushin]# let "a=2*3"
[root@web syushin]# echo $a
6
# 运算时两个 ** 表示乘方
[root@web syushin]# let "b=2**2"
[root@web syushin]# echo $b
4
1.2 引号符号
-
单引号
''
:所见即所得,单引号会去掉引号里面字符串的特殊含义,字符串是什么就是输出什么 -
双引号
""
:双引号与单引号作用类型,但是会解析特殊字符串,包括 ', $, \ 等,如果要忽略特殊字符,就可以用\
来转义。 -
反引号
``
:跟$()
一样,一般是把命令放到反引号里面,反引号里面的命令会先被执行,得到的结果会返回给反引号外面的命令执行
1.3 定向符号
定向符号包括如下几种:
定向符号 | 说明 |
---|---|
> | 标准输出重定向符号 |
>> | 标准输出追加重定向符号 |
< | 标准输入重定向符号 |
<< | 标准输入追加重定向符号 |
# > 标准输出重定向,先清空文件内容,再添加数据信息
$ echo "hello" > a.txt
# >> 在文件末尾追加信息,不会删除文件原有信息
$ echo "hello2" >> a.txt
# < 标准输入,从文件获取输入
$ xargs < a.txt
在Linux中,一切都是文件,每个命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
举例来说:标准输入重定向:>
等价于 1>
, 标准输入追加重定向:>>
等于 1>>
$ echo "hello" > a.txt
$ cat a.txt
hello
$ echo "hello" 1> b.txt
$ cat b.txt
hello
标错错误输入重定向就可以写为:2>
,标准错误追加重定向就是: 2>>
$ ech "test" 2> a.txt
$ cat a.txt
-bash: ech: 未找到命令
$ ech "test" 2>> a.txt
$ cat a.txt
-bash: ech: 未找到命令
-bash: ech: 未找到命令
如果希望将标准输出输入都重定向到一个文件中,可以这样写:
$ echo "hello" &>> a.txt
$ ech "hello" &>> a.txt
$ cat a.txt
hello
-bash: ech: 未找到命令
# 也可以使用 2>&1
$ echo "bbb" >> b.txt 2>&1
$ ech "bbb" >> b.txt 2>&1
$ cat b.txt
bbb
-bash: ech: 未找到命令
1.4 路径相关符号
.
:表示当前路径..
:表示上一级目录信息-
: cd命令中,-
表示上一次所在目录信息,实际上等价于$OLDPWD
变量的值~
: 用户的家目录,root用户是/root
,普通用户默认是/home/用户名
1.5 逻辑符号
Linux命令行中的逻辑符号跟一些编程语言的逻辑运算符一样,一旦确定逻辑表达式的真假,表达式后面的判断条件就不会执行。命令行中常用两个符号:
-
&&
:表示并且,示例:command1 && command2
,只有command1执行成功时,command2才执行 -
||
:表示或者,示例:command1 || command2
,只有当command1执行失败时,command2才执行
除此之外,命令行还常见下面的写法:
# 不管前面命令有没有执行成功,后面的命令继续执行
command1 ; command2 ; command3
2 正则表达式
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
在Linux中,正则表达式分为普通字符和元字符两种字符。
- 普通字符:就是一个简简单单的字符串,没有特殊含义;
- 元字符:有特殊意义的字符,可以被
grep
、sed
、awk
等命令工具所解析。
在Linux中,常用的正则表达式有:
- POSIX 基本正则表达式(BRE)引擎
- POSIX 扩展正则表达式(BRE)引擎
2.1 基本正则表达式
所有支持正则表达式的工具都兼容基本正则表达式,常见的基本正则表达式如下:
正则表达式 | 说明 |
---|---|
普通字符 |
匹配普通字符本身 |
. |
匹配任意一个字符 |
* |
匹配前面一个字符出现0次或者多次 |
^ |
匹配字符串的开头,如 ^a 表示匹配以字母a开头的 |
$ |
匹配字符串的结尾,如 a$ 表示匹配以字母a结尾的 |
[] |
匹配字符集合中包含的任意一个字符 |
[^] |
取反,匹配不在字符集合中的字符 |
[x-y] |
匹配指定字符范围内的字符 |
\ |
转义字符,将有特殊含义的字符去掉其含义 |
示例:以grep命令和下面文件为例
[root@web syushin]# cat a.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
1 gogle
2 goggle
3 google
123456
abcedf
匹配以root开头的行:
[root@web syushin]# grep '^root' a.txt
root:x:0:0:root:/root:/bin/bash
匹配以bash结尾的行:
[root@web syushin]# grep 'bash$' a.txt
root:x:0:0:root:/root:/bin/bash
匹配空行:
[root@web syushin]# grep '^$' a.txt
[root@web syushin]#
匹配任意一个字符在go和gle中间的行:
[root@web syushin]# grep 'go.gle' a.txt
2 goggle
3 google
匹配 go和gle 中间有任意多个字符的行:
[root@web syushin]# grep 'go.*gle' a.txt
1 gogle
2 goggle
3 google
匹配以数字开头的行:
[root@web syushin]# grep '^[0-9]' a.txt
1 gogle
2 goggle
3 google
123456
匹配第一个字符是数字1到2,第二个字符是空格的行:
[root@web syushin]# grep '[1-2] ' a.txt
1 gogle
2 goggle
匹配不是以字母开头的行:
[root@web syushin]# grep '^[^a-z]' a.txt
1 gogle
2 goggle
3 google
123456
2.2 扩展正则表达式
扩展正则表达式仅在部分程序中支持,比如 egrep
、grep -E
、awk
、sed -r
等。
正则表达式 | 说明 |
---|---|
`x | y` |
x? |
匹配0个或者1个前面的字符x |
x+ |
匹配至少1个字符x |
x{m} |
匹配前一个字符x出现连续m次 |
x{m,} |
匹配前一个字符x至少出现m次 |
x{m,n} |
匹配前一个字符x至少出现m次,最多出现n次 |
(xxx) |
将匹配的信息作为一个整体进行查询 |
示例:匹配至少包含1个数字1或者多个数字1的行:
[root@web syushin]# egrep '1+' a.txt
bin:x:1:1:bin:/bin:/sbin/nologin
1 gogle
123456
匹配至少包含2个字母o的行:
[root@web syushin]# egrep 'o{2,}' a.txt
root:x:0:0:root:/root:/bin/bash
3 google
匹配包含google或者goggle的行:
[root@web syushin]# egrep 'go(o|g)gle' a.txt
2 goggle
3 google
3 常见应用
3.1 获取网卡的IP地址
[root@web syushin]# ip a s ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:00:97:2e brd ff:ff:ff:ff:ff:ff
inet 192.168.18.150/24 brd 192.168.18.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::9e44:d201:cf43:83c5/64 scope link noprefixroute
valid_lft forever preferred_lft forever
方法一:sed方法
# 先过滤出ip地址所在行
[root@web syushin]# ip a s ens33| sed -n '3p'
inet 192.168.18.150/24 brd 192.168.18.255 scope global noprefixroute ens33
# 将ip地址前面的部分替换为空
[root@web syushin]# ip a s ens33| sed -n '3p' | sed 's#.*et ##g'
192.168.18.150/24 brd 192.168.18.255 scope global noprefixroute ens33
# 然后将ip地址后面的替换为空,得到ip地址
[root@web syushin]# ip a s ens33| sed -n '3p' | sed 's#.*et ##g' | sed 's#/24.*##g'
192.168.18.150
# 优化写法1:
[root@web syushin]# ip a s ens33| sed -n '3p' | sed -r 's#^.*et |/24.*##g'
192.168.18.150
# 优化写法2:使用括号在sed的后项引用前项写法
[root@web syushin]# ip a s ens33| sed -n '3p' | sed -r 's#^.*et (.*)/24.*#\1#g'
192.168.18.150
方法二:awk
[root@web syushin]# ip a s ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:00:97:2e brd ff:ff:ff:ff:ff:ff
inet 192.168.18.150/24 brd 192.168.18.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::9e44:d201:cf43:83c5/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# 获取指定行
[root@web syushin]# ip a s ens33 | awk 'NR==3'
inet 192.168.18.150/24 brd 192.168.18.255 scope global noprefixroute ens33
# 获取指定行的第2列
[root@web syushin]# ip a s ens33 | awk 'NR==3{print $2}'
192.168.18.150/24
# 指定/为分隔符,获取第1列得到IP地址
[root@web syushin]# ip a s ens33 | awk 'NR==3{print $2}'|awk -F'/' '{print $1}'
192.168.18.150
# awk支持指定多个分隔符,优化写法:
[root@web syushin]# ip a s ens33 | awk 'NR==3' | awk -F '[ /]' '{print $6}'
192.168.18.150
方法3:使用hostname命令
[root@web syushin]# hostname -I
192.168.18.150