shell编程“三剑客”小妙招之Sed!看完不信你不会!!

目录

shell编程之sed

sed编辑器介绍

1、在命令行定义编辑器命令

2、在命令行使用多个编辑器命令

3、从文件中读取编辑器命令

使用地址

删除行

插入和附和文本

修改行--c

转换命令--y

打印行--‘-n + p’ ‘=’

SED案例

补充其他内容:字符串运算符

read

declare命令

tr


shell编程之sed

sed编辑器介绍

sed编辑器被称作流编辑器( stream editor),和普通的交互式文本编辑器恰好相反。在交互式文本编 辑器中(比如vim),你可以用键盘命令来交互式地插入、删除或替换数据中的文本。流编辑器则会在编 辑器处理数据之前基于预先提供的一组规则来编辑数据流。

它是文本处理中非常有用的工具,能够完美的配合正则表达式使用,处理时,把当前处理的行存储在临 时缓冲区中,称为模式空间,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏 幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变。

sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文 本文件中。

sed编辑器会执行下列操作:

(1) 一次从输入中读取一行数据。

(2) 根据所提供的编辑器命令匹配数据。

(3) 按照命令修改流中的数据。

(4) 将新的数据输出到STDOUT。

1、在命令行定义编辑器命令

默认情况下, sed编辑器会将指定的命令应用到STDIN输入流上。这样你可以直接将数据通过管道输入 sed编辑器处理。这里有个简单的示例。

[root@kittod ~]# echo "This is a test" | sed 's/test/big test/'
 This is a big test
[root@kittod ~]# cat data1.txt 
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.
 The quick brown fox jumps over the lazy dog.
 [root@kittod ~]# sed 's/dog/cat/' data1.txt 
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.
 The quick brown fox jumps over the lazy cat

2、在命令行使用多个编辑器命令

要在sed命令行上执行多个命令时,只要用-e选项就可以了。

[root@kittod ~]# sed -e 's/brown/green/; s/dog/cat/' data1.txt 
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.
 The quick green fox jumps over the lazy cat
[root@kittod ~]# sed -e '
 > s/brown/green/
 > s/fox/elephant/
 > s/dog/cat/' data1.txt
 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.
 The quick green elephant jumps over the lazy cat.

3、从文件中读取编辑器命令

如果有大量要处理的sed命令,那么将它们放进一个单独的文件中通常会更方便一些。可以在sed 命令中用-f选项来指定文件。

[root@kittod ~]# cat script1.sed 
s/brown/green/
 s/fox/elephant/
 s/dog/cat/
 [root@kittod ~]# sed -f script1.sed data1.txt 
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.
 The quick green elephant jumps over the lazy cat

在这种情况下,不用在每条命令后面放一个分号。 sed编辑器知道每行都是一条单独的命令。跟在命令 行输入命令一样, sed编辑器会从指定文件中读取命令,并将它们应用到数据文件中的每一行上。

使用地址

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

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

1)以数字形式表示行区间

2)用文本模式来过滤出行

1、数字方式的行寻址

当使用数字方式的行寻址时,可以用行在文本流中的行位置来引用。 sed编辑器会将文本流中的第一行 编号为1,然后继续按顺序为接下来的行分配行号。 在命令中指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的 行。这里有个sed命令作用到指定行号的例子。

[root@kittod ~]# sed '2s/dog/cat/' data1.txt 
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.
 The quick brown fox jumps over the lazy dog

sed编辑器只修改地址指定的第二行的文本。这里有另一个例子,这次使用了行地址区间。

[root@kittod ~]# sed '2,3s/dog/cat/' data1.txt 
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.
 The quick brown fox jumps over the lazy dog

如果想将命令作用到文本中从某行开始的所有行,可以用特殊地址——美元符。

[root@kittod ~]# sed '2,$s/dog/cat/' data1.txt 
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.
 The quick brown fox jumps over the lazy cat

2、使用文本模式过滤器

该命令只作用到匹配文本模式的行上。虽然使用固定文本模式能帮你过滤出特定的值,就跟上面这个用 户名的例子一样,但其作用难免有限。 sed编辑器在文本模式中采用了一种称为正则表达式( regular expression)的特性来帮助你创建匹配效果更好的模式。 正则表达式允许创建高级文本模式匹配表达式来匹配各种数据。这些表达式结合了一系列通配符、特殊 字符以及固定文本字符来生成能够匹配几乎任何形式文本的简练模式。

必须用正斜线将要指定的pattern封起来。 sed编辑器会将该命令作用到包含指定文本模式的行上。 举个例子,如果你想只修改用户redhat的默认shell,可以使用sed命令

[root@kittod ~]# sed -n '/redhat/s/bash/csh/p' /etc/passwd
 redhat:x:1000:1000:redhat:/home/redhat:/bin/csh

3、命令组合

如果需要在单行上执行多条命令,可以用花括号将多条命令组合在一起。 sed编辑器会处理地址行处列 出的每条命令。

[root@kittod ~]# sed '2{
 > s/fox/elephant/
 > s/dog/cat/
 > }' data1.txt
 The quick brown fox jumps over the lazy dog.
 The quick brown elephant jumps over the lazy cat.
 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

两条命令都会作用到该地址上。当然,也可以在一组命令前指定一个地址区间。

[root@kittod ~]# sed '3,${
 > s/brown/green/
 > s/lazy/active/
 > }' data1.txt
 The quick brown fox jumps over the lazy dog.
 The quick brown fox jumps over the lazy dog.
 The quick green fox jumps over the active dog.
 The quick green fox jumps over the active dog.
 The quick green fox jumps over the active dog

删除行

‘d’删除

[root@kittod ~]# sed 'd' data1.txt

‘数字+d’删除第几行

[root@kittod ~]# sed '3d' data4.txt

This is line number 1.
 This is line number 2.
 This is line number 4

‘数字,数字d’删除第几到第几行

[root@kittod ~]# sed '2,3d' data4.txt

This is line number 1.
 This is line number 4

‘数字,$d’删除第几到最后所有的行

[root@kittod ~]# sed '3,$d' data4.txt

This is line number 1.
 This is line number 2

sed编辑器会删除两个指定行之间的所有行(包括指定的 行)

[root@kittod ~]# sed '/1/,/3/d' data4.txt

                                 行与行之间

This is line number 4

插入和附和文本

跟其他编辑器类似, sed编辑器允许向数据流插入和附加文本行。

两个操作的区别:

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

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

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

当使用附加命令时,文本会出现在数据流文本的后面。

[root@kittod ~]# echo "Test Line 2" | sed 'a\Test Line 1'
 Test Line 2
 Test Line 1

在命令行界面提示符上使用sed编辑器时,你会看到次提示符来提醒输入新的行数据。你必须在该行完成 sed编辑器命令。一旦你输入了结尾的单引号, bash shell就会执行该命令。

[root@kittod ~]# echo "Test Line 2" | sed 'i\
 > Test Line 1'
 Test Line 1
 Test Line 2

这样能够给数据流中的文本前面或后面添加文本,但如果要向要向数据流行内部插入或附加数据,你必 须用寻址来告诉sed编辑器你想让数据出现在什么位置。可以在用这些命令时只指定一个行地址。可以匹 配一个数字行号或文本模式,但不能用地址区间。这合乎逻辑,因为你只能将文本插入或附加到单个行 的前面或后面,而不是行区间的前面或后面。

下面的例子是将一个新行插入到数据流第三行前。

[root@kittod ~]# sed '3i\
 > This is an inserted line.' data4.txt
 This is line number 1.
 This is line number 2.
 This is an inserted line.
 This is line number 3.
 This is line number 4

下面的例子是将一个新行附加到数据流中第三行后。

[root@kittod ~]# sed '3a\
 > This is an appended line.' data4.txt
 This is line number 1.
 This is line number 2.
 This is line number 3.
 This is an appended line.
 This is line number 4

它使用与插入命令相同的过程,只是将新文本行放到了指定的行号后面。如果你有一个多行数据流,想 要将新行附加到数据流的末尾,只要用代表数据最后一行的美元符就可以了。

[root@kittod ~]# sed '$a\
 > This is a new line of text.' data4.txt
 This is line number 1.
 This is line number 2.
 This is line number 3.
 This is line number 4.
 This is a new line of text

同样的方法也适用于要在数据流起始位置增加一个新行。只要在第一行之前插入新行即可。要插入或附 加多行文本,就必须对要插入或附加的新文本中的每一行使用反斜线,直到最后一行。

[root@kittod ~]# sed '1i\
 > This is one line of new text.\
 > This is another line of newe text.' data4.txt
 This is one line of new text.
 This is another line of newe text.
 This is line number 1.
 This is line number 2.
 This is line number 3.
 This is line number 4

修改行--c

单独指定行进行修改

[root@kittod ~]# sed '3c\
> This is a changed line of text.' data4.txt


This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.

修改区间内容 如果是区间 是全部改成一条内容 而不是分别改成几条一样的内容

[root@kittod ~]# sed '2,3c\
> This is a new line of text.' data4.txt

This is line number 1.
This is a new line of text.
This is line number 4.

转换命令--y

转换命令会对inchars和outchars值进行一对一的映射。 inchars中的第一个字符会被转换为outchars中 的第一个字符,第二个字符会被转换成outchars中的第二个字符。这个映射过程会一直持续到处理完指 定字符。如果inchars和outchars的长度不同,则sed编辑器会产生一条错误消息。 这里有个使用转换命令的简单例子。

[root@kittod ~]# sed 'y/123/789/' data5.txt
 This is line number 7.
 This is line number 8.
 This is line number 9.
 This is line number 4.
 This is line number 7 again.
 This is text you want to keep.
 This is the last line in the file

转换命令是一个全局命令,也就是说,它会将文本行中找到的所有指定字符自动进行转换,而不会考虑 它们出现的位置。

[root@kittod ~]# echo "This 1 is a test of 1 try." | sed 'y/123/456/'
 This 4 is a test of 4 try

打印行--‘-n + p’ ‘=’

除了使用p标记和替换命令显示sed编辑器修改过的行。

另外有3个命令也能用来打印数据流中的信息:

1)p命令用来打印文本行;

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

3)l(小写的L)命令用来列出行。

1、打印行

它所做的就是打印已有的数据文本。打印命令最常见的用法是打印包含匹配文本模式的行。

[root@kittod ~]# cat data4.txt 
This is line number 1.
 This is line number 2.
 This is line number 3.
 This is line number 4.
 [root@kittod ~]# sed -n '/number 3/p' data4.txt 
This is line number 3

在命令行上用-n选项,你可以禁止输出其他行,只打印包含匹配文本模式的行。也可以用它来快速打印 数据流中的某些行。

[root@kittod ~]# sed -n '/3/{
 > p
 > s/line/test/p
 > }' data4.txt
 This is line number 3.
 This is test number 3

2、打印行号

等号命令会打印行在数据流中的当前行号。行号由数据流中的换行符决定。每次数据流中出现一个换行 符, sed编辑器会认为一行文本结束了。

[root@kittod ~]# cat data1.txt 
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.
 The quick brown fox jumps over the lazy dog.
 [root@kittod ~]# sed '=' data1.txt 
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.
5
 The quick brown fox jumps over the lazy dog

利用-n选项,你就能让sed编辑器只显示包含匹配文本模式的行的行号和文本。

3、列出行

列出( list)命令( l)可以打印数据流中的文本和不可打印的ASCII字符。任何不可打印字符要么在其八 进制值前加一个反斜线,要么使用标准C风格的命名法(用于常见的不可打印字符),比如\t,来代表制 表符。

[root@kittod ~]# cat data6.txt 
This    
line    
contains    
tabs.
 [root@kittod ~]# sed -n 'l' data6.txt 
This\tline\tcontains\ttabs.$

SED案例

1、把/etc/passwd 复制到/root/test.txt,用sed打印所有行;
[root@localhost ~]# sed -n  '1,$p' test.txt
 [root@localhost ~]# sed -n p test.txt

 2、打印test.txt的3到10行;
[root@localhost ~]# sed -n '3,10'p test.txt

 3、打印test.txt 中包含’root’的行;
[root@localhost ~]# sed  -n '/root/p' test.txt

 4、删除test.txt 的15行以及以后所有行;
[root@localhost ~]# sed -i '15,$d' test.txt
 [root@localhost ~]# sed -e '15,$d' test.txt(只会在命令行删除,不会真的删除原文件内容)等
同于[root@localhost ~]# sed '15,$d' passwd

 5、删除test.txt中包含’bash’的行;
[root@localhost ~]# sed '/bash/'d test.txt

 6、替换test.txt 中’root’为’toor’;
[root@localhost ~]# sed 's/root/toor/g' test.txt

 7、替换test.txt中’/sbin/nologin’为’/bin/login’;
[root@localhost ~]# sed 's#/sbin/nologin#/bin/login#' test.txt

 8、删除test.txt中5到10行中所有的数字;
[root@localhost ~]# sed '5,10s/[0-9]//g' test.txt

 9、删除test.txt 中所有特殊字符(除了数字以及大小写字母);
[root@localhost ~]# sed 's/[^0-9a-zA-Z]//g' test.txt

 10、在test.txt 20行到末行最前面加’aaa:’
 [root@localhost ~]# sed '20,$s/^.*$/aaa:&/g' test.txt

 11、复制/etc/grub2.cfg到/root/grub2.cfg,删除文件中所有以空白开头的行行首的空白字符;
[root@localhost ~]# sed 's/^[[:space:]]//' grub2.cfg

 12、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
[root@localhost ~]# sed   's/^#[[:space:]]*//'  /etc/fstab

 13、给文件/root/anaconda-ks.cfg每一行行首增加#号
[root@localhost ~]# sed  's/^.*$/#&/' /root/anaconda-ks.cfg

 14、在/etc/fstab文件中不以#开头的行的行首增加#号;
[root@localhost ~]# sed 's/^[^#]/#&/' /etc/fstab


 15、利用sed 取出ifconfig命令中本机的IPv4地址
[root@localhost ~]# ifconfig  |sed -n '2p' | sed -r "s/.*inet[[:space:]]*//" | 
sed -r "s/[[:space:]]*netmask.*//"
 192.168.168.128

 16、统计centos安装光盘中Package目录下的所有rpm文件的以.分隔倒数第二个字段的重复次数
[root@localhost ~]#  ls /mnt/Packages/|grep "rpm$"|sed -r 's@.*\.
 (.*)\.rpm@\1@'|sort|uniq -c   
 
 1085 i686
 1216 noarch
 2319 x86_64

补充其他内容:字符串运算符

$1 表示第一个参数 $n表示第几个参数

set -- 取消了某个功能

shift 换挡 表示$1第一个参数会被取消 去echo执行第二个参数 再一个shift echo出来的时第三个参数 以此类推... 参数内容换成了之后的 但是参数没变还是$1 但是内容可能换成了$2 $3 的内容

expr 数字 + 数字 表示两数相加 要之间有空格 例如2空格+2空格

[root@kittod ~]# echo -n i have a cat
i have a cat[root@kittod ~]#
[root@kittod ~]# echo -e i\thave\ta\tcat
ithavetatcat
[root@kittod ~]# echo -e "i\thave\ta\tcat"
i have a cat
[root@kittod ~]# echo "1 2 3"
1 2 3
[root@kittod ~]# echo -e "1\t2\t3"
1 2 3
[root@kittod ~]# echo -e "1 2 3"
1 2 3

read

读取指定个数的字符 利用echo又可以输出
read    -n      个数        名称
读取   不换行   字符的个数    

[root@node02 ~]# read -n 5 name
named[root@node02 ~]# echo $name
named

判断答案型
[root@node02 ~]# cat read01.sh
#!/bin/bash
#read yes or no

read -n1 -p "Do you want to continue [Y/N]?" answer
case $answer in
       Y|y)
echo "fine,continue";;
       N|n)
echo "ok,good bye";;
       *)
echo "error choice";;
esac
exit 0

[root@node02 ~]# bash read01.sh
Do you want to continue [Y/N]?y fine,continue

[root@node02 ~]# bash read01.sh
Do you want to continue [Y/N]?n ok,good bye

[root@node02 ~]# bash read01.sh
Do you want to continue [Y/N]?f error choice

declare命令

注:declare命令还可输出所有的变量、函数、整数和已经导出的变量
+/- "-"可用来指定变量的属性,"+"则是取消变量所设的属性
-p:显示所有变量的值
-i:将变量定义为整数,在之后就可以直接对表达式求值,结果只能是整数。如果求值失败或者不是
整数,就设置为0。
-r:将变量声明为只读变量。只读变量不允许修改,也不允许删除。(也可使用readonly定义只读变
量)
-a:变量声明为数组变量。但这没有必要,所有变量都不必显示定义就可以用作数组。事实上,在
某种意义上,似乎所有变量都是数组,而且赋值给没有下标的变量与赋值给下标为0的数组元素相同。
-f:显示所有自定义函数,包括名称和函数体。
-x:将变量设置成环境变量。可使用+x将变量变成非环境变量


#声明整数型变量
[root@node02 ~]# declare -i ab    --declare 输入为整数 则可正常输出
[root@node02 ~]# ab=23
[root@node02 ~]# echo $ab
23

#改变变量属性
[root@node02 ~]# declare -i ef   --declare若输出的是非整数 输出为0
[root@node02 ~]# ef=1
[root@node02 ~]# echo $ef
1
[root@node02 ~]# ef="wer"
[root@node02 ~]# echo $ef
0

#设置变量只读
[root@kittod ~]# declare -r ab
[root@kittod ~]# ab=55
-bash: ab: readonly variable
[root@kittod ~]# echo $ab
23

tr

[root@kittod ~]# echo "HELLO WHO IS THIS" | tr 'A-Z' 'a-z'
hello who is this
#tr '' '' 将前面的''内的类型  换成后面''中的内容类型

[root@kittod ~]# echo "Hello 123 world 456" | tr -d '0-9'
Hello world
#tr -d 删除后面要求的序列号

[root@kittod ~]# echo "GNU is not UNIX. Recursive right ?" | tr -s ' '
GNU is not UNIX. Recursive right ?
#tr -s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串

[root@kittod ~]# echo hehe | tr '[:lower:]' '[:upper:]'
HEHE
#tr '' '' 将前面的''内的类型  换成后面''中的内容类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值