基础正则表达式字符

  • ^word 待查找的字符串在行首

  • word$ 待查找的字符串在行尾

  • . 代表一定有一个任意字符的字符

  • \ 转义字符

  • * 重复零个到无穷多个的前一个字符

  • [list] 从字符集合的RE字符里面找出想要选取的字符

  • [n1-n2] 从字符集合的RE字符里面找出想要选取的字符范围

  • [^list] 从字符集合的RE字符里面找出不要选取的字符或范围

  • [n,m] 连续n到m个的前一个RE字符

  • + 重复一个或一个以上的前一个RE字符

  • ? 零个或一个的前一个RE字符

  • | 用或的方式找出数个字符串

  • () 找出“组”字符串

  • ()+ 多个重复组的判别

注意,正则表达式的特殊字符与一般命令行输入命令的通配符并不相同

sed

sed本身是一个管道命令,可以分析standard input 而且sed还可以将数据进行替换、删除、新增、选取特定行等功能
sed [-nefr] [动作]
-n 使用安静模式,在一般sed用法中,所有来自stdin的数据一般都会被列出屏幕中,但如果加上了-n参数后,则只有经过sed特殊处理的才会被列出来
-e 直接在命令行模式上进行sed的动作编辑
-f 直接将sed的动作写在一个文件内,-f filename则可以执行filename内的sed动作
-r sed的动作支持的是扩展性语法(默认是基础正则表达式)
-i 直接修改读取的文件内容,而不是由屏幕输出

动作说明: [n1[,n2]] function
n1,n2 不见得一定会存在,一般代表选择进行动作的行数

function有下面这些参数:
a 新增,a的后面可以接字符串,而这些字符串会在新的一行出现
c 替换,c的后面可以接字符串,这些字符串可以替换n1, n2之间行
d 删除,后面不需要接参数
i 插入,i的后面可以接字符串
p 打印,将某个选择的数据打印出来
s 替换,可以直接进行替换的工作,通常s动作可以搭配正则表达式

下面是示例:
以行为单位的新增/删除功能

nl /etc/passwd | sed '2,25d'

     1  root:x:0:0:root:/root:/bin/bash
    26  tomcat:x:999:998::/home/tomcat:

nl /etc/passwd | sed '2a drink tea'

     1  root:x:0:0:root:/root:/bin/bash
     2  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
drink tea
     3  bin:x:2:2:bin:/bin:/usr/sbin/nologin
     4  sys:x:3:3:sys:/dev:/usr/sbin/nologin
     5  sync:x:4:65534:sync:/bin:/bin/sync
     (略...)

以行为单位的替换与显示功能

nl /etc/passwd | sed '2,5c new line'

     1  root:x:0:0:root:/root:/bin/bash
new line
     6  games:x:5:60:games:/usr/games:/usr/sbin/nologin
     7  man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
     (略...)

sed 's/要被替换的内容/新的字符串/g'
cat /etc/man.config | grep 'MAN' | sed 's/#.*$//g' | sed '/^$/d'

将/etc/man.config中存在MAN的行筛选出来,并把开头是#的行去掉(先置换成空行,再讲空行删除)

直接修改文件内容

sed -i '$a # this is a new line' regular_express.txt
由于$代表最后一行,而a的操作是新增,因此是该文件最后新增一行

awk

相比于sed常常作用于一整行的处理,awk则比较倾向于将一行分出数个“子弹”来处理
awk '条件类型1{动作1} 条件类型2{动作2}...' filename

示例

[dmtsai@study ~]$ last -n 5  <==仅取出前五行
dmtsai pts/0 192.168.1.100 Tue Jul 14 17:32 still logged in
dmtsai pts/0 192.168.1.100 Thu Jul 9 23:36 - 02:58 (03:22)
dmtsai pts/0 192.168.1.100 Thu Jul 9 17:23 - 23:36 (06:12)
dmtsai pts/0 192.168.1.100 Thu Jul 9 08:02 - 08:17 (00:14)
dmtsai tty1 Fri May 29 11:55 - 12:11 (00:15)

若想取得第一列和第三列的数据:

[dmtsai@study ~]$ last -n 5 | awk '{print $1 "\t" $3}'
dmtsai 192.168.1.100
dmtsai 192.168.1.100
dmtsai 192.168.1.100
dmtsai 192.168.1.100
dmtsai Fri

awk是以行尾一次处理的单位,而以字段为最小的处理单位,可以通过内置的变量来查看处理的是第几行第几列
NF 每一行拥有的字段总数
NR 目前处理的第几行数据
FS 目前的分割字符

示例:

Name 1st 2nd 3th
VBird 23000 24000 25000
DMTsai 21000 20000 23000
Bird2 43000 42000 41000

如何帮我计算每个人的总额呢?而且我还想要格式化输出喔!我们可以这样考虑:

第一行只是说明,所以第一行不要进行加总(NR==1 时处理);
第二行以后就会有加总的情况出现(NR>=2 以后处理)

cat pay.txt | \ 
> awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" } 
> NR>=2{total = $2 + $3 + $4 
> printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'

      Name 1st 2nd 3th Total
     VBird 23000 24000 25000 72000.00
    DMTsai 21000 20000 23000 64000.00
     Bird2 43000 42000 41000 126000.00

bash sed awk

登陆发表评论