您的位置:首页 > 其它

流编辑器sed使用总结及利用sed从文本中提取字符串的方法

2015-10-11 16:31 525 查看
sed 是一个编辑器,但它与其它大多数编辑器不同。除了不面向屏幕之外,它还是非交互式的,我们常用的vim编辑器则是交互式的。

这意味着必须将要对数据执行的命令插入到命令行或要处 理的脚本中。sed 在一个文件(或文件集)中非交互式、并且不加询问地接收一系列的命令并执行它们。因而,它流经文本就如同水流经溪流一样,因而 sed 恰当地代表了流编辑器,可以对文件或者文件集批量的进行删除 替换 插入 追加等操作。

流编辑器非常适合于执行重复的编辑,这种重复编辑如果由人工完成将花费大量的时间。

其参数可能和一次性使用一个简单的操作所需的参数一样有限, 或者和一个具有成千上万行要进行编辑修改的脚本文件一样复杂。

这正是我们常用的交互式编辑器VIM的缺点所在啊,所以2者结合,非常实用!

sed 是 Linux 和 UNIX 工具箱中最有用的工具之一,且使用的参数非常少。

sed每次从输入(该输入可以是管道或者文件)中读取一行,用提供的编辑命令匹配数据、按命令中指定的方式修改流中的数据,然后生成的数据输出到STDOUT。在流编辑器将所有命令与一行数据进行匹配后,它会读取下一行数据并重复这个过程。在流编辑器处理完流中的所有数据行后,它就会停止。

sed命令行格式为:

         sed [-nefri] ‘command’ 输入文本        

常用选项:

        -n∶使用安静(silent)模式。sed默认的处理结果是输出到STDOUT。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

        -e∶直接在指令列模式上进行 sed 的动作编辑(可以同时执行多条操作命令);

        -f∶直接将 sed 的动作写在一个文件内, -f filename 则可以执行 filename 内的sed 动作;

        -r∶sed 的动作命令是扩展型正则表达式。(预设是基础正则表达式)

        -i∶直接修改读取的档案内容,而不是由STDOUT输出。       

常用命令:

        a   ∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)

        c   ∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!

        d   ∶删除,删除行;

         i   ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);

         p  ∶列印,亦即将某个选择的资料印出。可用于查找功能,sed -n ‘/查找字符串/p’可实现对字符串的查找,类似于grep。通常 p 会与参数 sed -n 一起运作

         s  ∶取代,直接进行取代的工作,通常这个 s 的动作可以搭配正则表达式

下面来详细说一下sed的使用方法

1)在命令行定义编辑命令

$ echo "This is a test" | sed 's/test/big test/'

This is a big test

 

$ cat data1

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy dog.

 

$ sed 's/dog/cat/' data1

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy cat.

2)在命令行使用多个编辑器命令(要使用-e选项)

$ sed -e 's/brown/green/; s/dog/cat/' data1

The quick green fox jumps over the lazy cat.

The quick green fox jumps over the lazy cat.

The quick green fox jumps over the lazy cat.

The quick green fox jumps over the lazy cat.

3)从文件中读取编辑器命令(使用-f选项)

$ cat script1.sed

s/brown/green/

s/fox/elephant/

s/dog/cat/

 

$ sed -f script1.sed data1

The quick green elephant jumps over the lazy cat.

The quick green elephant jumps over the lazy cat.

The quick green elephant jumps over the lazy cat.

The quick green elephant jumps over the lazy cat.

4)替换标记

关于substitute命令如何替换字符串中匹配的模式需要注意一点,就是在默认情况下它只替换每行中出现的第一处。要让替换命令对一行中不同地方出现的文本都起作用,必须使用替换标记(substitution flag)

s/pattern/repacement/flags

1> 数字,表明新文本将替换第几处模式匹配的地方;

2> g,表明新文本将会替换所有已有文本出现的地方;

3> p,表明原来行的内容要打印出来;

4> w file,将替换原来行的结果写到文件中。

 

$ echo "This is a test" | sed -n 's/test/big test/p'

This is a big test

注意:-n选项将禁止sed编辑器输出,但p替换标记会输出修改过的行,将二者配合全盘则会只输出被substitute命令修改过的行。

 

5)替换字符

$ sed 's/\bin\/bash/\/bin\/csh/' /etc/passwd

sed编辑器可以用感叹号用作分隔符,使得路径名更容易被读取和理解

$ sed 's!/bin/bash!/bin/cash!' /etc/passwd

 

6)使用地址

默认情况下,在sed编辑器中使用的命令会作用于文本数据的所有行。如果只想作用于特定的某行或某些行,你必须用行寻址(line addressing)。

在sed编辑器中有两种形式的行寻址:

1》行的数字范围;

2》用文本模式来过滤出某行。

两种形式都使用相同的格式来指定地址:

[address]command

也可以为特定的地址将多个命令放在一起:

address{

     command1

     command2

     command3

}

1> 数字方式的行寻址

$ sed '2s/dog/cat/' data1 

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy dog.

 

$ sed '2,3s/dog/cat/' data1 

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy dog.

 

$ sed '2,$s/dog/cat/' data1 

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy cat.

The quick brown fox jumps over the lazy cat.

2> 使用文本模式过滤器

格式如下:

/pattern/command

$ echo "This is a test" | sed '/test/s/test/TEST/'

This is a TEST

3> 组合命令

如果需要在单行上执行多条命令,可以用花括号将多条命令组合在一起。

$ sed '2{

> s/fox/elelhant/

> s/dog/cat/

> }' data1

The quick brown fox jumps over the lazy dog.

The quick brown elelhant jumps over the lazy cat.

The quick brown fox jumps over the lazy dog.

The quick brown fox jumps over the lazy dog.

7)删除行

$ cat data2

line1

line2

line3

line4

 

$ sed '3d' data2

line1

line2

line4

你可以删除用两个文本模式来删除某个范围内的行,但这么做时要小心。你指定的第一个模式会“打开”行删除功能,第二个模式会“关闭”行删除功能。sed编辑器会删除两个指定行之间的所有行(包括指定的行)

$ sed '/1/,/3/d' data2

line4

如果“打开”了删除功能,而没有“关闭”,则会删除之后所有的数据。

$ sed '/1/,/5/d' data2

8)插入和附加文本

1》插入(insert)命令i会在指定行前增加一个新行;

2》追加(append)命令a会在指定行后增加一个新行。

不能在单个命令行上使用这两条命令。你必须指定是要将行插入还是附加到另一行。格式如下:

sed '[address]command\

new line'

new line中文本将会出现在sed编辑器输出中你指定的位置。记住,当使用插入命令时,文本会出现在数据流文本的前面,而当使用附加命令时,文本会出现在数据流文本的后面:

$ echo "Test line 2" | sed 'i\Test line 1'

Test line 1

Test line 2

 

$ echo "Test line 2" | sed 'a\Test line 1'

Test line 2

Test line 1

9)修改行

修改(change)命令允许修改数据流中整行文本的内容。它跟插入和附加命令的工作机制一样,你必须在sed命令中单独指定新行。

$ sed '3c\This is a changed line' ./data2

line1

line2

This is a changed line

line4

也可以在修改命令中使用地址区间,但结果可能不是你想要的(因为它是包括区间所在的行):

$ sed '2,3c\This is a changed line' ./data2

line1

This is a changed line

line4

10)转换命令

转换(transform, y)命令是唯一可以处理单个字符的sed编辑命令。转换命令格式如下:

[address]y/inchars/outchars/

转换命令会进行inchars和outchars值一对一映射。

$ sed 'y/1234/6789/' data2

line6

line7

line8

line9

转换命令是全局的,也就是说,它会自动替换文本行中找到的指定字符的所有实例,

$ echo "this 1 is a test of 1 try." | sed 'y/123/456/'

this 4 is a test of 4 try.

11)回顾打印

这里有3条也能用来打印数据流中的信息的命令:

1> 小写p命令用来打印文本行;

2> 等号(=)命令用来打印等号;

3> 小写l命令用来列出行。

$ echo "This is a test" | sed 'p'

This is a test

This is a test

 

$ sed '=' data1

1

The quick brown fox jumps over the lazy dog.

2

The quick brown fox jumps over the lazy dog.

3

The quick brown fox jumps over the lazy dog.

4

The quick brown fox jumps over the lazy dog.

 
上面介绍了sed的一些基础使用方法,下面就我实际遇到的一个问题来实战一下!

现在需要在kernel启动后解析kernel的commandline,来获取需要设置的ip netmask等网络参数。

首先查看/proc/cmdline,如下:

console=ttyS0,115200 rdinit=/sbin/init ipaddr=10.0.14.143 netmask=255.255.255.252 gw=10.0.12.1

当然可以写个程序,进行字符串分析,这是最保守的方法,也是最笨的方法。。。需要自己去写字符串分析。

还是要用最简单的方法来解决问题才好。

在脚本中用sed实现如下:

[cpp] view
plaincopy





#!/bin/bash  

  

ip=`sed -n 's/ /\n/gp' /proc/cmdline | sed -n '/ipaddr/p' | sed -n 's/ipaddr=//gp'`  

netmask=`sed -n 's/ /\n/gp' /proc/cmdline | sed -n '/netmask/p' | sed -n 's/netmask=//gp'`  

gw=`sed -n 's/ /\n/gp' /proc/cmdline | sed -n '/gw/p' | sed -n 's/gw=//gp'`  

  

if [ "$ip" != "" -a "$netmask" != "" ]; then  

    ifconfig eth0 $ip netmask $netmask  

fi  

  

if [ "$gw" != "" ]; then  

    route add default gw $gw   

fi  

这个脚本就可以实现ipaddr netmask gw字符串的提取,以及使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: