首页 > 其他 > 详细

sed高级应用

时间:2021-03-29 20:50:21      阅读:43      评论:0      收藏:0      [点我收藏+]
更改文件中的内容,并将匹配到的文件存入fig.interleaf中

[root@wang ~]# cat tent
<para>
This is a test paragraph in Interleaf style ASCII. Another line
in a paragraph. Yet another.
<Figure Begin>
v.11111110000001111110000
1000001001000100000
000
<Figure End>
<para>
More lines of text to be found after the figure.
These lines should print.

[root@wang ~]# sed ‘
/<Figure Begin>/,/<Figure End>/{    #匹配其中的值
w fig.interleaf     #将匹配的值保存
/<Figure End>/i\     插入值
.FG<insert figure here>.FE
d   #删除之前匹配到的值
}‘ tent
<para>
This is a test paragraph in Interleaf style ASCII. Another line
in a paragraph. Yet another.
.FG
<insert figure here>
.FE
<para>
More lines of text to be found after the figure.
These lines should print.

匹配到的文件已放入新文件中

[root@wang ~]# cat fig.interleaf
<Figure Begin>
v.11111110000001111110000
1000001001000100000
000
<Figure End>
多行删除

[root@wang ~]# cat text
This line is followed by 1 blank line

This line is followed by 2 blank line


This line is followed by 3 blank line

 

This line is followed by 4 blank line

 


this is the end.

[root@wang ~]# sed ‘/^$/{N;/^\n$/d}‘ text
This line is followed by 1 blank line

This line is followed by 2 blank line
This line is followed by 3 blank line

This line is followed by 4 blank line
this is the end.

当空行为偶数时,则全部删除,当空行为奇数行时,则保存一行

 

 多行转换

[root@wang ~]# cat text
Here are examples of the UNIX
System. Where UNIX
System appears, it should be the UNIX
Operating System.

[root@wang ~]# sed ‘
> /UNIX$/{    #匹配UNIX值
> N              #匹配当前行与下一行
> /\nSystem/{         #换行的值为System,则执行括号内的
> s// Operating &/   #在匹配的值后加入
> P     #打印
> D     #删除
> }} ‘ text
Here are examples of the UNIX Operating
System. Where UNIX Operating
System appears, it should be the UNIX
Operating System.
[root@wang ~]# cat text
Hello world runtime
sean, where runtime
sean, jjyy runtime
it sean.

[root@wang ~]# sed ‘
> /runtime$/{
> N
> /\nsean/{
> s// it &/
> P
> D
> }}‘ text
Hello world runtime it
sean, where runtime it
sean, jjyy runtime
it sean.

  

  

[root@wang ~]# cat abc
1
2
11
22
111
222
[root@wang ~]# sed ‘
> /1/{   #在模式空间匹配1
> h      #将匹配到的数复制到保持空间
> d      #在模式空间删除所有的1,则模式空间只留有2
> }
> /2/{   #在模式空间匹配2 
> G      #将保持空间的数追加到模式空间
> }‘ abc
2
1
22
11
222
111
技术分享图片

 

 

  

[root@wang ~]# cat qwe 
hello world
hello runtime

hehe
xiix

henhen
haha

end

[root@wang ~]# sed ‘
> /^$/!{    #匹配非空的值,!表示取反
> H            #将模式空间的值追加保持空间
> d             # 删除模式空间匹配到的值
> }
> /^$/{     #匹配空值
> x            #交换保持空间和模式空间的内容,此时的模式空间为非空的所有值,保持空间为空值
> s/^\n/<p>/  #匹配开头的值,在开头加入<p>
> s/$/<\/p>/   #匹配结尾的值,在句尾加入</p>;因为有/p有特殊字符要用\转译
> G
> }‘ qwe
<p>hello world
hello runtime</p>

<p>hehe
xiix</p>

<p>henhen
haha</p>

  

Sed的基本用法
概念及作用
sed和grep类似,也是一种文件编辑器
sed是一个流编辑器,所谓流编辑器是指sed每次只从文件或stdin中读入一行,将读入的行保存至模式空间然后根据指定的要求对其进行处理,并将处理后的结果输出至屏幕,接着读入下一行,整个文本的过程如流水线般被逐行处理后输出。
sed主要用来自动编辑一个或多个文件,可以将数据进行增删改查等特定工作,简化对文件的反复操作.

格式
sed [参数] ‘命令’ 文件

参数
-f :将sed的动作写在一个文件内,用–f filename 执行filename内的sed动作;
-i :直接修改文件内容,(没有备份时慎重操作);
-n :只打印模式匹配的行,与grep相似
-r :支持扩展表达式;

命令
a\ 在当前行下面插入文本;
i\ 在当前行上面插入文本;
c\ 把当前行改为新的文本;
d 删除,将选择的内容删除
D 删除模板第一行
s 替换指定字符 (最常用)
p 打印模板块的行。(常常和 -n配合使用)
P 打印模板块的第一行;

标记
g 表示行内全部替换,ng表示第n个匹配的开始进行替换
w 表示把行写入一个文件
\1 字串匹配标记(划重点)
& 已匹配字符串标记

部分测试

```
1. 替换
`echo book | sed ‘s/book/books/‘`
将book替换为books
[root@wang ~]# echo book | sed ‘s/book/books/‘
books
先将777和test写入到cs文件中,然后使用 sed命令将test替换为TEST,再用-n p 组合查看
[root@wang ~]# echo test >> cs | echo 777 >> cs
[root@wang ~]# cat cs
777
test
[root@wang ~]# sed ‘s/test/TEST/‘ cs
777
TEST
[root@wang ~]# sed -n ‘s/test/TEST/p‘ cs
TEST
[root@wang ~]# echo test >> cs | echo 777 >> cs
[root@wang ~]# sed -n ‘s/test/TEST/p‘ cs
TEST
TEST
可以看到,通过使用-n p 运行sed之后就只显示经过修改的结果.
2. 全局替换
echo sksksksksksk | sed ‘s/sk/SK/ng‘
[root@wang ~]# echo sksksksksk | sed ‘s/sk/SK/2g‘
skSKSKSKSK
[root@wang ~]# echo sksksksksk | sed ‘s/sk/SK/3g‘
skskSKSKSK
[root@wang ~]# echo sksksksksk | sed ‘s/sk/SK/4g‘
skskskSKSK
[root@wang ~]# echo sksksksksk | sed ‘s/sk/SK/g‘
SKSKSKSKSK
这里能看出g的作用,
当n=1时,这段代码就是将每一个sk替换为SK,
为2时,从第二个开始的sk换为SK
以此类推
ng就是从第n个开始,将字符进行替换
3。删除
拷贝一份htttpd文件,添加几个空行
[root@wang ~]# sed -n p httpd | head -10
#!/bin/bash

util=apr-util-1.6.1
apr=apr-1.7.0
httd=httpd-2.4.46

yum -y groups mark install "Development Tools"
yum -y install openssl-devel pcre-devel expat-devel libtool wget 
useradd -r -g apache apache 
ls | grep apr && ls | grep httpd
[root@wang ~]# sed ‘/^$/d‘ httpd | head -10
#!/bin/bash
util=apr-util-1.6.1
apr=apr-1.7.0
httd=httpd-2.4.46
yum -y groups mark install "Development Tools"
yum -y install openssl-devel pcre-devel expat-devel libtool wget 
useradd -r -g apache apache 
ls | grep apr && ls | grep httpd
if [ $? != 0 ]; then
	cd /usr/src
接着对没有空白行的文本进行操作
删除第五行
[root@wang ~]# sed ‘5d‘ httpd | head -6
#!/bin/bash

util=apr-util-1.6.1
apr=apr-1.7.0

yum -y groups mark install "Development Tools"
原内容
[root@wang ~]# cat httpd
#!/bin/bash

util=apr-util-1.6.1
apr=apr-1.7.0
httd=httpd-2.4.46
yum -y groups mark install "Development Tools"
yum -y install openssl-devel pcre-devel expat-devel libtool wget 
sed ‘2,$d‘ passwd删除第二行之后的所有(包括第二行)
[root@wang ~]# sed ‘2,$d‘ httpd | head -10
#!/bin/bash
从这里可以发现’n,md’是删除n-m行(包括n和m)
```

```
字符串标记
在正则中,用\w\+匹配每一个单词
在sed中,&则表示匹配到的字符
echo "this is a test line" | sed ‘s/\w\+/[&]/g‘
用来给匹配到的每一个单词加上[]
[root@wang ~]# echo "this is a test line"
this is a test line
[root@wang ~]# echo "this is a test line" | sed ‘s/\w\+/[&]/g‘
[this] [is] [a] [test] [line]
子串匹配
我们假定a b c d 为一个字符串,那么a b c d 则为 a b c d的四个子串
在搞懂这个概念之后,进行如下命令
[root@wang ~]# echo a b c d | sed ‘s/\([a-z]\) \([a-z]\) \([a-z]\) \([a-z]\)/\4/‘
d
[root@wang ~]# echo a b c d | sed ‘s/\([a-z]\) \([a-z]\) \([a-z]\) \([a-z]\)/\3/‘
c
[root@wang ~]# echo a b c d | sed ‘s/\([a-z]\) \([a-z]\) \([a-z]\) \([a-z]\)/\2/‘
b
[root@wang ~]# echo a b c d | sed ‘s/\([a-z]\) \([a-z]\) \([a-z]\) \([a-z]\)/\1/‘
a
这一段命令是分别匹配了a b c d的四个子串,然后输出N个子串
[root@wang ~]# echo a b c d | sed ‘s/\([a-z]\) \([a-z]\) \([a-z]\) \([a-z]\)/\2\1\4\3/‘
badc
而这一段命令则是将匹配的子串输出,且中间没有隔断
[root@wang ~]# echo a b c d | sed ‘s/\([a-z]\) \([a-z]\) \([a-z]\) \([a-z]\)/\2,\1,\4,\3/‘
b,a,d,c
这一段则是用’,‘隔开
子串的匹配方式应和原文本保持一致,不然会匹配不到


```

```
选定范围
在sed中,范围的用’,(逗号)’
例如我们前面的删除第二行之后的所有就用了2-$($和以前一样,表示结尾,同样^和以前一样表示开头)
打印从第五行开始,已if开头的之间的行
root@wang ~]# sed -n ‘5,/^if/p‘ httpd
httd=httpd-2.4.46

yum -y groups mark install "Development Tools"
yum -y install openssl-devel pcre-devel expat-devel libtool wget 
useradd -r -g apache apache 
ls | grep apr && ls | grep httpd
if [ $? != 0 ]; then

追加
追加分为行上(a),行下(i),本行

行上追加
就是在匹配到的行前面一行进行追加操作
[root@wang ~]# sed ‘/^if/i/123321‘ httpd
/123321
if [ $? != 0 ]; then
tar xf $util.tar.gz $apr.tar.gz $httpd.tar.gz
/123321
if [ $? = 0 ]; then
在匹配到的行下面一行进行追加
[root@wang ~]# sed ‘/^if/a/321‘ httpd
if [ $? != 0 ]; then
/321
cd /usr/src
if [ $? = 0 ]; then
/321

本行追加
本行追加又有在匹配到的字符后直接追加和在行尾追加两种

字符后追加
[root@wang ~]# sed ‘s/^if/&777/‘ httpd
if777 [ $? != 0 ]; then

tar xf $util.tar.gz $apr.tar.gz $httpd.tar.gz
if777 [ $? = 0 ]; then
在行末追加
sed ‘/test/s/$/777/‘ httpd
[root@wang ~]# sed ‘/if/s/$/777/‘ httpd
if [ $? != 0 ]; then777

if [ $? = 0 ]; then777

```


awk的使用方法
简介
awk是一种优良的文本处理器,它可以扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。它也是一种用于处理文本的编程语言工具.也正是因为它的强大功能,所以它也是处理文本所用的三个工具中最复杂的一个.

格式
awk [选项] ‘命令’ 文件

awk脚本的组成
awk脚本是由模式和操作组成的

模式

正则表达式:正则表达式用/ /加在中间

关系表达式:大于,小于,大于等于,小于等于,等于,不等于

模式匹配表达式:用 ~ 表示匹配, !~ 表示不匹配

BEGIN语句块,pattern语句块,END语句块

操作
操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是 :

变量或数组赋值
输出命令
内置函数
控制流语句
基本结构
awk ‘BEGIN{ print “头部分”} pattern{ 命令} END{ print “尾部分”}’
这三部分都是可选的,也就是说可以不出现在脚本语句中

awk测试
awk的内置变量非常的多,我们直接使用习题来进行测试

1. 如何使用awk输出 hello word
awk ‘BEGIN{ print "hello word}’

```
[root@wang ~]# awk ‘BEGIN{ print"hello word" }‘
hello word
使用这种方法awk就相当于我们用的echo
2. 那么我们在输出一个符号 ‘ 呢
awk ‘BEGIN { print "这是一个符号 (‘"‘"‘)" }‘
[root@wang ~]# awk ‘BEGIN { print "符号(‘"‘"‘)" }‘
符号(‘)
我们可以在对这段简化
[root@wang ~]# awk ‘BEGIN { print "符号(‘\‘‘)"} ‘
符号(‘)
在这里使用转义符 \ 对上一段的“”进行了替换,简化了代码

还可以再使用变量,即-v参数例如
[root@wang ~]# awk -v sq=\‘ ‘BEGIN{ print "符号("sq")"}‘
符号(‘)
我们在这里一开始使用-v参数定义了一个名为sq的变量,内容为‘ 在后面的awk语句中就可以直接使用
需要注意的是,每定义一个变量,就需要一个-v参数
扩展 \47表示单引号’
\42表示双引号"
[root@wang ~]# awk ‘BEGIN { print "符号(\47 \t \42)" }‘
符号(‘ 	 ")

 使用awk对文本进行处理
在进行测试之前,先准备一个名为mail-list的文件,内容是

Amelia       555-5553     amelia.zodiacusque@gmail.com    F
Anthony      555-3412     anthony.asserturo@hotmail.com   A
Becky        555-7685     becky.algebrarum@gmail.com      A
Bill         555-1675     bill.drowning@hotmail.com       A
Broderick    555-0542     broderick.aliquotiens@yahoo.com R
Camilla      555-2912     camilla.infusarum@skynet.be     R
Fabius       555-1234     fabius.undevicesimus@ucb.edu    F
Julie        555-6699     julie.perscrutabor@skeeve.com   F
Martin       555-6480     martin.codicibus@hotmail.com    A
Samuel       555-3430     samuel.lanceolis@shu.edu        A
Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R

一个名为data的文件,内容为

Jan  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Apr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Aug  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dec  17  35  61 401

Jan  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Apr  21  70  74 514
1. 在mail-list中对li进行匹配
awk ‘/li/ { print $0 }‘ mail-list
匹配当前文件中所有li的行
[root@wang ~]# awk ‘/li/ { print $0 }‘ mail-list
Amelia       555-5553     amelia.zodiacusque@gmail.com    F
Broderick    555-0542     broderick.aliquotiens@yahoo.com R
Julie        555-6699     julie.perscrutabor@skeeve.com   F
Samuel       555-3430     samuel.lanceolis@shu.edu        A
对字符串进行匹配需要用/ /包起来;
$0 这个变量包含执行过程中当前行的文本内容

2. 匹配data中长度大于80的所有字段
awk ‘length($0) > 80‘ data
[root@wang ~]# awk ‘length($0) > 80‘ data
[root@wang ~]# awk ‘length($0) > 10‘ data
Jan  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Apr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Aug  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dec  17  35  61 401
Jan  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Apr  21  70  74 514
匹配字段使用length()函数
发现没有输出结果,说明没有匹配到长度大于80的字段

输出data中长度最长的行长度
[root@wang ~]# awk ‘{ if (length($0) > max ) max = length($0) }END {print max }‘ data
19
在这里,我们在awk中添加了if语句,去寻找data中最长的字段长度,最后对其进行输出
[root@wang ~]# expand data | awk ‘{ if (x < length($0)) x = length($0) } END { print "maximum line length is " x }‘
maximum line length is 19
这里使用了expand命令,它也是一种查看文件的命令
5.打印至少有一个字段的每一行
[root@wang ~]# awk ‘NF > 0‘ data
Jan  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Apr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Aug  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dec  17  35  61 401
Jan  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Apr  21  70  74 514
NF表示总字段数 NF > 0 表示字段数大于零的行
6.打印从0到100的七个随机数
[root@wang ~]# awk ‘BEGIN { for (i = 1; i <= 7; i++)print int (101 * rand()) }‘
93
59
30
58
74
79
44
rand()也是一个函数,它用来生成随机数,此处用法为: n*rand()生成一个0-n的随机数,多次调用会产生相同的随机数,所以产生的并不是随机数,而是伪随机数
在mail-list中匹配12 在data中匹配21
[root@wang ~]# awk ‘/12/ { print $0 }/21/ { print $0 }‘ mail-list data
Anthony      555-3412     anthony.asserturo@hotmail.com   A
Camilla      555-2912     camilla.infusarum@skynet.be     R
Fabius       555-1234     fabius.undevicesimus@ucb.edu    F
Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
Jan  21  36  64 620
Apr  21  70  74 514
直接在awk后面写上两个文件,即可对两个文件进行匹配
那么,如果有一个文件不存在呢 ,分别写错第二个和第一个文件,得出结果如下:
[root@wang ~]# awk ‘/12/ { print $0 }/21/ { print $0 }‘ mail-list date
Anthony      555-3412     anthony.asserturo@hotmail.com   A
Camilla      555-2912     camilla.infusarum@skynet.be     R
Fabius       555-1234     fabius.undevicesimus@ucb.edu    F
Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
awk: 命令行:1: 致命错误:无法以读模式打开文件“date”(没有那个文件或目录)
[root@wang ~]# awk ‘/12/ { print $0 }/21/ { print $0 }‘ mail-lis data
awk: 致命错误:无法以读模式打开文件“mail-lis”(没有那个文件或目录)

通过这个结果可以看出,写错第二个文件时,不影响第一个文件的处理,但是写错第一个文件,那么第二个文件也不会进行处理。
所以我们可以得出结果当前面的文件出错,后面的不会进行,但是后面文件的正确与否不影响前面文件的处理

匹配当前目录下3月所修改的文件大小总和
[root@wang ~]# ls -l
总用量 36
drwxr-xr-x  3 root   root   40 3月   9 03:11 alpine
-rw-------. 1 root   root 1235 12月 16 00:40 anaconda-ks.cfg
drwxr-xr-x  2 root   root   51 3月   8 18:07 apache
-rw-r--r--  1 root   root   18 3月  25 23:16 cs
-rw-r--r--  1 root   root  321 3月  26 00:45 data
-rw-r--r--  1 root   root 1099 3月  25 00:10 httpd
-rwxr-xr-x  1 root   root  157 3月  23 21:13 loop.sh
-rw-r--r--  1 root   root  661 3月  26 00:45 mail-list
-rwxr-xr-x  1 root   root  429 3月  23 00:07 random.sh
drwxr-x--x  2 redhat root 4096 3月  20 00:24 test
drwxr-xr-x  3 root   root   63 3月  24 22:53 web
-rwxr-xr-x  1 root   root  649 3月  23 23:56 wm.sh
[root@wang ~]# ls -l | awk ‘$6 == "3月" { sum += $5 }END { print sum }‘   #月份需要输入的跟文件月一样,不能文件使用中文而命令使用英文
7584
我们在这里先查看了文件的特点,发现第六列是月份,第五列是大小,那么我们就可以使用上面的命令,指定第六列,然后对第五列的值进行累加,最后输出
这里面有一个$5,$6的参数,这是指定列, $n意思是指定第n列(字段

```
##  基本正则表达式

```text
//元字符
    .           //任意单个字符
    []          //匹配指定范围内的任意单个字符
    [^]         //匹配指定范围外的任意单个字符
//匹配次数(贪婪模式)
    *           //匹配其前面的任意单个字符任意次
    .*          //任意长度的任意字符
    \?          //匹配其前面的任意单个字符1次或0次
    \+          //匹配其前面的任意单个字符至少1次
    \{m,n\}     //匹配其前面的任意单个字符至少m次,至多n次
//位置锚定
    ^           //锚定行首,此字符后面的任意单个字符必须出现在行首
    $           //锚定行尾,此字符前面的任意单个字符必须出现在行尾
    ^$          //空白行
    \<或\b       //锚定词首,其后面的任意单个字符必须作为单词首部出现
    \>或\b       //锚定词尾,其前面的任意单个字符必须作为单词尾部出现
/分组
    \(\)
    例:\(ab\)*
    //后向引用
        \1      //引用第一个左括号以及与之对应的右括号所包括的所有内容
        \2      //引用第二个左括号以及与之对应的右括号所包括的所有内容

```

## 3\. 扩展正则表达式

```text
//字符匹配
    .       //匹配任意单个字符
    []      //匹配指定范围内的任意单个字符
    [^]     //匹配指定范围外的任意单个字符
//次数匹配
    *       //匹配其前面的任意单个字符任意次
    ?       //匹配其前面的任意单个字符1次或0次
    +       //匹配其前面的任意单个字符至少1次
    {m,n}   //匹配其前面的任意单个字符至少m次,至多n次

//位置锚定
    ^       //锚定行首,此字符后面的任意单个字符必须出现在行首
    $       //锚定行尾,此字符前面的任意单个字符必须出现在行尾
    ^$      //空白行
    \<或\b       //锚定词首,其后面的任意单个字符必须作为单词首部出现
    \>或\b       //锚定词尾,其前面的任意单个字符必须作为单词尾部出现
//分组
    ()      //分组
    \1,\2,\3,....
   例:(ab)*
    //后向引用
        \1      //引用第一个左括号以及与之对应的右括号所包括的所有内容
        \2      //引用第二个左括号以及与之对应的右括号所包括的所有内容
//或者
    |       //or 默认匹配|的整个左侧或者整个右侧的内容
    //例:C|cat表示C或者cat,要想表示Cat或者cat则需要使用分组,如(C|c)at

```

  

 

sed高级应用

原文:https://www.cnblogs.com/wangming/p/14593779.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!