sed&awk 第三版笔记

Sed, awk  都可以 -f scriptfile inutfile

 

元字符 .   匹配除换行符以外的任意单个字符,在awk句点也能匹配换行符

元字符 *  匹配任意一个包括零个在它前面的字符 这个*理解很重要,任意一个指的是一  个或者多个也可以没有

举列:

yexiang@ubuntu:<~>$ cat test1.txt

yexiang,hello world .

I am  a new student.

m

my name is yexiang

 

yexiang@ubuntu:<~>$ grep "m*" test1.txt

yexiang,hello world .

I am  a new student.

m

my name is yexiang

 

这里 m* 把所有的行都打印出来了,那是因为我可以匹配到m 行也可以匹配不到m行(0个),

 

yexiang@ubuntu:<~>$ grep "m." test1.txt

I am  a new student.

my name is yexiang

这里并没有打印出 m 单独的行,因为 m. 是指的必须要2个字符

 

 

[...] 匹配方括号中的字符类的任意一个。如果方括号中的第一个字符为脱字符(^),则表示否定匹配,既匹配除了换行符和类中列出的那些字符以外的所有字符。Awk中可匹配换行符,连字符(-) 用于表示字符的范围,如果类中的第一个字符为右括号( ] ), 则表示它是类的成员,所有其他的元字符在被指定为类中成员时都会失去它们原来的含义

 

^ 如果作为正则表达式的第一个字符,则表示匹配行的开始,在awk中匹配字符串的开始,即使字符串包含嵌入的换行符

 

$ 如果作为正则表达式的最后一个字符,则表示匹配行的结尾,在awk中匹配字符串的结尾,即使字符串中包含嵌入的换行符。

 

\{n,m\} 匹配它前面某个范围内单个字符出现的次数,\{n\} 将匹配n次出现,\{n,\} 至少匹配n次出现,\{n,m\} 匹配nm之间的任意次出现。

 

\ 转义随后的字符

 

扩展的元字符:(egrep, awk

+  匹配前面的正则表达式的一次或多次出现

?匹配前面的正则表达式的零次或一次出现

| 指定可以匹配其前面的或者后面的正则表达式

() 对正则表达式分组

{n,m} 匹配它前面某个范围内单个字符出现的次数,{n} 将匹配n次出现,{n,} 至少匹配n次出现,{n,m} 匹配nm之间的任意次出现。

 

 

字符类[ ]中的特殊字符:

\ 转义任意特殊字符

- 当它不在第一个或者最后一个位置的时候,表示一个范围

^ 仅当第一个位置的时候表示反转匹配

 

如果指定多个连续的字符,可以使用多个字符类。

[ ][ ][ ]...

 

如果为了匹配运算操作符,那么可以把 - 号放在开头或者结尾让其失去特殊的意义

[-+*/]

 

使用 .* 匹配的范围总是最大,因为匹配任意字符的零次或者多次出现

 

2个定位元字符 ^, $

可以一起使用 ^$来匹配空行

^.*$ 匹配整个行


词首定位符 \<  如:/\<love/

词尾定位符 \>  如:/love\>/

 


指定跨度元字符 \{n,m\} , n m 0-255之间的整数。

{n} 将匹配n次出现,

{n,} 至少匹配n次出现,

{n,m} 匹配nm之间的任意次出现。

 

 

等价于 \{0,1\}

*  等价于 \{0,\}

+  等价于 \{1,\}

 

举例:

[0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\}  可以匹配类似这样的电话号码 xxx-xx-xxxx

 

选择性元字符 |

分组元字符 ()

可使用 | () 来对选择性进行分组

如: compan(y|ies) 单数或者复数匹配

 

 

SED

Sed 维护一种模式空间,既一个工作区或临时缓冲区,当应用编辑命令时将在那里存储单个输入行。一次一行的设计是一个sed的优点,在读取庞大的文件时不会出错

 

/s/CA/California/g  替换 CA California

/yexiang/s/CA/California/g  只替换包含了yexiang 的行 才将 CA 替换为 California

上面的相当于向前提供了地址。

 

1. 如果没有提供地址,那么命令将用于每一行

2. 如果只有一个地址,那么命令将应用于与这个地址匹配的每一行

3. 如果指定了由逗号分隔的两个地址,那么命令应用于匹配第一个地址的第一行和它后面的行,直到匹配第二个地址的行(包括此行)

4. 如果地址后面跟有感叹号,那么命令就应该用于不匹配该地址的所有行

 

d  删除所有行

1d 删除第一行

$d 删除输入的最后一行

 

当正则表达式作为地址提供时,这个命令只影响与这个模式匹配的行,必须封闭在/ 中,如: /^$/d 只删除空行,其他行不变

 

/^\.TS/,/^\.TE/d  它删除了从第一种模式匹配的行开始,到由第二种模式匹配的行(包括此行在内)为止的所有行

 

50,$d 删除50行开始到最后一行的所有行

 

行地址和模式地址混合使用:

1,/^$/d 删除第一行开始到第一个空行的所有行。 由于sed没办法决定第二个地址是否会匹配,所以如果没有空行,那么它将删除所有的行。

 

/^\.TS/,/^\.TE/!d  感叹号会反转匹配的意义,下面的脚本将删除在两种匹配的以外的所有行

 

sed分组 用大括号 {} 将一个地址嵌套在另一个地址中。或者在相同的地址上应用多个命令。

/^\.TS/,/^\.TE/{

/^$/d

}

左大括号必须在行末,右大括号本身必须单独占一行,确保在大括号后没有空格。

可使用大括号编辑命令括起来对某个范围的行应用多个命令

/^\.TS/,/^\.TE/{

/^$/d

s/^\.ps 10/.ps 8/

s/^\.vs 12/.vs 10/

}

上面的格式是:

Address {

 Command 1

 Command 2

 Command 3

}

 

sed  -f  scriptfile  inputfile

sed 不会改变原始文件,除非重定向到输入文件,一般输出到屏幕上

为了保持修改可以保持到另外文件中去

sed  -f  scriptfile  inputfile > outputfile

 

diff inputfile outputfile

Inputfile 会显示 <  

Outputfile 会显示 >

 

 

Address {

 Command 1

 Command 2

 Command 3

}

每个命令都可以有自己的地址并允许有多层分组

在命令后添加空格会产生语法错误,因为命令的结束必须在行末尾处

特殊: 命令直接可以用分号放在同一行上 command1command2,但不提倡

 

注释:

第一个字符必须是#号,可以使用反斜杠来结束前面的行使得注释可以继续多行。

如果跟在 #号后面的是字符n #n 那么脚本不会自动产生输出 这个指令 -n 是等价的

 

替换:

[address]s/pattern/replacement/flags

这里修饰替换的标志flags是:

n1512之间的数字,表示对文本模式中指定模式第n次出现的情况进行替换

g:  对模式空间中所有出现的情况进行全局更改,没有g通常只有第一次出现情况

p:  打印模式空间内容

W  file  将模式空间的内容写到文件file中。

 

如果没有指定地址,那么就应用于pattern 匹配的所有行,如果正则表达式来提供地址,并且没有指定模式,那么替换命令匹配由地址匹配的内容

 

如果模式中包含了斜杠\, 那么可以选择另外一个字符作为限定符。如感叹号:

s!/usr/mail!/usr2/mail!

Flags可以进行组合使用 如 gp

Replacement 是一个字符串。在replacement 匹配的部分,只用下列字符有特殊含义:

& 用正则表达式匹配的内容进行替换

\n 匹配第n个字串,这个字串以前在pattern中用 \( \) 指定

\ 当替换部分包含&\,和替换命令的定界符时候可以用\转义它们

 

s/./>/2 >替换第二个 .

如果一行中有3. 那么默认替换只替换第一个. 所以默认的数字是1

 

替换元字符:

反斜杠\, &, \n 反斜杠一般用于转义其他元字符,但是它在替换字符串中也用于包含换行符

 

s/./\

/2

这样是用换行符替换第二个.  换行符后面不能有空格

s/ORA/O`Reilly \& Associates\g  转义&符号

如果 没有加 \ 转换& 符号,上面的输出为 O`Reilly ORA Associates ,用正则表达式匹配的内容进行替换

上面的&符号是替换的固定的单词,也可以替换一个模式匹配的内容如:

s/See Section [1-9][0-9]*\.[1-9][0-9]*/(&)/ 如果是匹配到 See Section 1.4 结果为

(See Section 1.4)

 

sed 转义的圆括号括住正则表达式任意部分并且保存它以备回调,一行最多允许保存9次, \nn1-9数字。

 

s/\(See Section \) \([1-9][0-9]*\.[1-9][0-9]*\)/\1\\fB\2\\fP/

这里的\1 回调 See Section

这里的\2 回调 [1-9][0-9]*\.[1-9][0-9]

 

再举例: 交换

 

First Second

sed  s/\(.*\):\(.*\)/\2:\1/

结果

Second First

 

删除:

/^$/d 删除空行

 

追加插入和更改

追加 [line-address]a\

text

插入 [line-address]i\

  text

更改 [address]c\

 text

 

插入命令是在模式空间当前行之前

追加命令是在模式空间当前行之后

更改命令是取代模式空间的内容

这些命令的每一个都要求后面跟一个\反斜杠用于转义第一个行尾。Text必须从下一行开始

要输入多行文本,每个连续的行都必须用反斜杠结束。最后一行列外

/<Larry`s Address>/i\

4700 Cross Court \

French Lick,IN

如果文本中有一个字面的 \,那么要添加一个\进行转义

 

追加和插入命令只能用于一行,更改命令可以用于多行

 

列表:

列表命令 l 用于显示模式空间的内容,将非打印的字符显示为两个数字的ASCII代码,

 

转换:

[address]y/abc/xyz/ 该行上的 a都被转换为x,不管a后面是否跟了b

这个功能在转换大小写有用

 

打印:

打印命令P #n 相当于 -n抑制了打印

 

打印行号:

[line-address] =  

 

下一步 next 命令 (n) 输出模式空间的内容,然后读取下一行

[address]n

 

/^\.H1/{

n

/^$/d

}     这个删除.H1 之后的空行

读和写命令: 直接作用于文件本身

[line-address]r   file

[line-address]w  file

 

退出:

退出命令 q会使sed停止读取新的输入行。它的语法为

[line-address]q,它只适用于单行,如果找到了匹配的行就立刻停止

sed 100qtest  // 打印100行退出,有点类似head命令

 

高级sed命令

1. 多行空间模式:(N,D,P)对应于单行模式的 (n,d,p

2. 采用保持空间来保存模式空间的内容并使它可用于后续的命令(H,h,G,g,x

3. 编写使用分支和条件指令的脚本来更改控制流程(:、bt

 

D :删除多行模式空间的第一行,

d :  删除模式空间的内容

 

N: 读取新的输入行,并将它添加到模式空间的现有内容之后来创建多行模式空间,模式空间最初的内容和新的输入行之间用换行符分隔,在模式空间中嵌入的换行符可以利用转义序列\n来匹配,多行模式空间中,元字符^匹配空间中第一个字条,而不匹配换行符后面的字符,$只匹配模式空间中最后的换行符,而不匹配任何嵌入的换行符,

n :  输出模式空间的内容,然后读取新的输入行。

 

P :多行打印输出多行模式空间的第一部分。直到第一个嵌入的换行符

 

 

模式空间是容纳当前输入行的缓冲区,还有一个称为保持空间的顶留缓冲区。

模式空间内容可以复制到保持空间,保持空间也可以复制到模式空间。

保持空间最常用的用途是:

当改变模式空间中的原始内容时,用于保留当前输入行的副本。

 

Hh,将模式空间的内容复制或追加到保持空间

G g,  将保持空间的内容复制或追加到模式空间

x 交换保持空间和模式空间的内容

 

小写命令复制缓冲区内容,大写命令追加缓冲区内容

 

分支(b) 和测试 (t) ,分支是无条件转移,测试是有条件转移

标签:是任意不多于7个字符的序列

 

mylabel

b mylabel

[address]b[label] 将控制转移到另一行上

如果没有给出label,控制就转移到脚本的结尾处

如果当前匹配地址上进行了成功的替换,那么t命令就会转移标签或者结尾处

[address]t[label]

 

 

AWK

awk是一个非常棒的数字处理工具。相比于sed常常作用于一整行的处理,awk则比较倾向于将一行分为数个字段来处理。运行效率高,而且代码简单,对格式化的文本处理能力超强

awk的一般语法格式为:
awk [-参数 变量] 'BEGIN{初始化}条件类型1{动作1}条件类型2{动作2}。。。。END{后处理}'
其中:BEGINEND中的语句分别在开始读取文件(in_file)之前和读取完文件之后发挥作用,可以理解为初始化和扫尾。


 -v var=$v v值赋值给var,如果有多个变量要赋值,那么就写多个-v,每个变量赋值对应一个-v
e.g. 要打印文件a的第num行到num+num1行之间的行, 
awk -v num=$num -v num1=$num1 'NR==num,NR==num+num1{print}' a 


awk  {print Hello world}  file

awk  BEGIN {print Hello world}

 

如果忽略了文件名,那么awk期望得到来自键盘的输入。

 

awk  -f  script  file

 

awk 可以在任何地方进行注释。以#开头,换行符结尾

如果以命令行的方式提供awk程序,而不是将它写入一个文件中,那么程序的任何地方都不能用单引号,否则shell将对它进行解释而导致错误

 

用来分隔字段的字符被称为分隔符。一般为空格或者制表符

awk 允许使用字段操作符 $来指定字段。在该操作符后面跟着一个数字或者变量用于标识字段的位置。$1 标识第一个字段,$2 标识第二个字段,$0 表示整个输入的记录

 

ls -al | awk '{print $1}'

ls -al | awk '{print $3,$4}'

 

可以用任何计算值为整数的表达式表示一个字段。

echo a b c d | awk BEGIN { one=1;two=2} {print $(one+two)}  输出c

 

可以在命令行中使用 -F 选项来改变字段的分隔符。后面跟着分隔符

awk -F\t

在脚本中指定分隔符是一个好的习惯。因为这个是必须在读取第一行输入的时候之前执行,所以必须在由BEGIN 规则控制的操作中指定这个变量

BEGIN {FS = ,}

 

分隔符默认是空白字符,可以设置单个字符,也可以设置为正则表达式,字段分隔符将是与正则表达式匹配的“最左边最长的非空的不重叠的 子串” 如:

 

1. FS = \t

2. FS = \t+

如果用于 abc\t\tdef ,第一种将分隔3个字段,中间一个为空字段, 如果是第二种将分隔2个字段,

3. FS = [:\t]  3个字符的任意一个字符都可以被解释为字段分隔符

 

 

awk {print  } 空字符会打印换行

测试匹配指定的字段: ~ 操作符 , !~ ~ 相反

 

常量有2种类型:字符串类型或数字类型 “red,1 。字符串必须用引号括起来

转义字符:

\r 回车

\t 水平制表符

\v 垂直制表符

\ddd 将字符表示为1-3位的八进制

\xdex 将字符表示为十六进制

\c 任何需要字面表示的字符 ,例如 “for

 

 

操作符有 +-*/% ,^, **-=+=*= /= , ++,-- , < , > , <= , >= , == , != , ~ ,!~

|| ,&& , !

 

/^$/{

 Print x+=1

}   // 碰到一个空行就打印 x

 

/^$/{

  ++x

}

END{

 print x

}  // 读完最后一个空行的时候再打印x

 

系统变量:

NF : 定义了当前输入记录中的字段个数

如:cat b
1:2:3
4:5:6

 

awk -F ':' '{print NF}' b的输出为

3

3

 

NR 已经读出的记录数

awk -F ':' '{print NF}END{print NR}' b

3

3

2

 

FS: 输入字段分隔符(缺省为:space:),相当于-F选项

awk -F ':' '{print}' a       awk 'BEGIN{FS=":"}{print}' a 是一样的

 

RS输入记录分隔符,缺省为"\n"

合理的使用RSFS可以使得awk处理更多模式的文档,例如可以一次处理多行

例如,如果文件ccat c
hello_world; I_want_to_go_swimming_tomorrow;ha_ha


运行 awk 'BEGIN{ RS = ";" } {print $1}' c 的结果为
hello_world
I_want_to_go_swimming_tomorrow
ha_ha

因为默认 FS为空格,所以上面打印是正确的,并没有分隔

如果运行 awk 'BEGIN{ FS=_;RS = ";" } {print $1}' c 的结果为

hello

I

ha

 

OFS输出字段分隔符(缺省为:space:

c文件为例

如果运行 awk 'BEGIN{ FS=_;RS=";";OFS=.} {print $1,$2}' c 的结果为

hello.world

I.want

ha.ha

 

ORS输出记录分隔符,缺省为换行符,控制每个print语句后的输出符号

awk 'BEGIN{ FS=_;RS=";";OFS=.; ORS = "_"} {print $1,$2}' c 的结果为

hello.world_I.want_ha.ha_

 

FNR   当前文件的记录数 一般来说和 NR一样

 

格式化打印:

print 提供了自动换行

printf 不提供自动换行

 

printf 格式化说明:和C语言基本一样

c   ASCII字符

d   十进制整数

s   字符串

u  无符号十进制

x  无符号十六进制小写

X  无符号十六进制大写

- 进行左对齐,默认右对齐

 

 

如: printf(%d\t%d\n,$5,$9)

 

printf 语句输出的默认精度可以通过设置系统变量OFMT来改变。

 

向脚本传递参数:

 

变量可以在命令行上设置,在脚本的后面,文件的前面

 

awk -f scriptfile var=vaule inputfile ,等号的两边不允许出现空格

 

命令行中: awk -f xxx high=100 low=60 file

脚本中可以: awk -f xxx high=$1 low=$2 file

 

环境变量或命令的输出结果也可以作为变量的值来传递。

如:

 awk xxx dir=$cwd file

 awk xxx dir=pwd file  // 反引号

 

所以可以使用命令行参数定义系统变量,如 FS, NR

 

命令行参数的一个重要限制就是在BEGIN过程中不可用。

POSIX awk 提供了一个解决方法,就是在脚本前 使用 -v 选项 ,那么BEGIN过程就能得到

If (experssion) action1

else action2

If(expression) action1; else action2

条件操作符: expr ? action1: action2

 

 

循环: whiledofor

While(condition)

     action

 

do

     action

while(condition)

 

For(xxx;xxx;xxx)

循环中可以用continue到循环的顶部,break退出循环,还有另外2个语句可以控制

next 语句能够导致读入下一个输入行,并返回脚本的底部。Next语句的典型应用是可以连续的从文件读取内容,忽略脚本的其他操作直到文件读完。系统变量FILENAME提供了当前文件的名字,可以编写模式:

FILENAME==acronyms{

     action

     next

 }

这使得对文件acronyms的每行都执行action指定操作。完成操作后输入下一个新行。

 

exit 语句使主输入退出循环并将控制移动到END规则。如果END存在的话。如果没有定义END规则,或在END中应用exit语句,则终止脚本。可以使用一个表达式作为参数。 该表达式将作为awk的退出状态码。如果没有提供表达式,那么返回0。如果exit语句设置了一个初始值。然后在END中再次调用没有参数的exit,则使用第一个值。

awk {

     .....

     exit 5

}

END{exit}// 状态码是5

 

数组: awk中不必为数组指定大小。只需要指定标识符。

awk中所有的数组都是关联数组。关联数组的独特之处在于它的下标可以是字符或一个数值。顺序不一定有序。但是对于数值型下标也能够顺序访问数值中的所有元素。

array[$1]=$2

array[BASIC] = Instruction Code

 

特殊的for循环访问关联数组所有元素

for(var in array)

     array[var]

 

这个语法可以应用于数值型下标数组,但是数组中的条目顺序是随机的。

关联数组awk中所有数字的下标都是字符串类型。即使使用数字作为下标,awk 将自动把它们转为字符串

 

关键字 in 也是一个操作符。用在条件表达式中测试一个下标是否是数组的成员。

Item in array

If(BASIC in acro)

 

内置函数split 能够将任何字符串分解到数组的元素中。这个函数对于从字段中提取“子字段”很有用。

n = split(string,array,separator)

如果没有指定分隔符separator,那么将使用分隔符 FS

 

删除数组元素:

delete array[xxx]

 

Awk 支持线性数组,不支持多维数组,但是可以提供下标模拟多维数组

File_array[NR,i] 表示第NR个记录的第i个字段

If((i,j) in  array)

 

系统变量数组:

ARGC     命令行参数的个数

ARGV     命令行参数数组

ARGIND 当前被处理文件的ARGV标志符

 

数组ARGV中下标从0开始,最后一个是ARGC-1, 第1个数组是调用的程序名或者文件名

ENVIRON 环境变量数组

 

函数:

算术函数: 

cos(x), exp(x),int(x),log(x),sin(x),rand(),srand(x)

Rand()生成一个0-1之间的浮点数伪随机数

 

字符串函数:

 

gsub(r,s,t)

字符串t中用字符串s替换和正则表达式r匹配的所有字符串,返回替换的个数,如果没有给出t默认为$0

 

index(s,t)

返回子串t在字符串s中位置,如果没有指定s,则返回0

 

length(s)

返回字符串s的长度,如果没有给出s,返回$0的长度

 

match(s,r)

如果正则表达式rs中出现,则返回出现的起始位置,如果在在s中没发现r,则返回0,设置RSTARTRLENGTH的值, RSTART记录的是匹配子串的开始位置。RLENGTH记录的匹配字符串的字符数。不匹配时候 RSTART=0, RLENGTH=-1

split(s,a,sep)

使用字段分隔符sep将字符串s分解到数组a的元素中,返回元素的个数,如果没有给出sep,则使用FS

 

sprintf(fmt,expr)

expr使用printf格式说明

 

sub(r,s,t)

在字符串t中用s替换正则表达式r的首次匹配,如果成功则返回1,否则返回0,如果没有给出t,默认为$0

 

substr(s,p,n)

返回字符串s中从位置p开始最大长度为n的子串,如果没有给出n,返回从p开始剩余的字符串

 

tolower(s)

将字符串s中的所有大写字符转换为小写,并返回新串。

 

toupper(s)

将字符串s中的所有小写字符转换为大写,并返回新串。

 

gsub(r,s)

可以实现输入字符串中所有位置的替换

 

自定义函数:

function xxx(xxx,xxx, 局部变量,局部变量){

 

}

参数一般是传值,数组是引用

如果把多个函数保存在多个文件中,awk允许使用多个-f 选项来指定多个程序文件。

awk -f xxx -f xxxx

 

getline 函数

调用只能写成 getline 不用加()

getlinenext 类似, next 读取下一行并将控制传递给脚本的顶部,但是getline读取之后并没有改变脚本的控制

返回:

1 . 如果能够读到一行

0.  如果到了文件结尾

-1. 如果遇到了错误

 

从文件中读取:

getline < filename

while((getline < filename) > 0)

将输入赋给一个变量:

getline input

 

从管道读取输入:

who am i| getline

 

Close()函数用于关闭打开的文件和管道,原因有几个,第一,每次你只能打开一定数量的管道。你必须用close() 来关闭一个你用过的管道。通常是当getline返会0-1,如:close(who)

 

system函数执行一个以表达式给出的命令。

如: system(mkdir tt)

 

直接向文件或管道输出:

print , printf > filename  , >> filename

print, printf | command  如: print | wc -w

 

使用#!语法调用awk

#!/bin/awk  -f

#!/bin/sh

/bin/awk  {printf x}

 

如果使用了 #!/bin/awk  -f ,那么当执行 myscript  filename 相当于

/bin/awk  -f  myscript  filename

 

BEGING .END 可以多次出现,执行顺序安装他们定义的顺序

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HarkerYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值