awk文本处理工具和编程语言

功能说明:awk是一个强大的文本处理工具和编程语言,主要用于在 Unix 和 Linux 系统中对文本进行格式化、分析和处理。

语  法:awk -f ‘scripts’ -v var=value filename

awk ‘BEGIN{ print “start” } pattern{ commands } END{ print “end” }’ filename

补充说明:awk 可以逐行读取文件或者输入流(包括stdin),按照用户指定的模式和操作来处理文本数据,特别适用于结构化的文本(如表格、CSV、日志等结构化数据)。awk可在命令行中使用,但更多是作为脚本来使用。awk作为一门编程语言有很多内建的功能,比如数组、函数等,这是它和C语言的相似之处。

   项:

-F                         指定分隔符(可以是字符串或正则表达式)

-f ‘scripts’             从脚本文件’scripts’中读取awk命令

-v var=value       赋值变量,将外部变量传递给awk

awk脚本基本结构:

pattern                 用于匹配特定的行

{ commands }     用于对匹配的行执行操作

filename                     要被awk处理的文件

一个awk脚本通常由BEGIN语句+模式匹配+END语句三部分组成,这三部分都是可选项。工作步骤:

第一步,执行BEGIN语句

第二步,从文件或标准输入读取一行,然后再执行pattern语句,以此类推,逐行扫描文件到文件全部被读取

第三步,执行END语句

awk内置变量:

awk默认将每行文本按照空格或特定分隔符分成多个字段(列),每个字段可以通过 $ 符号访问:

$0          当前记录(行)

$n          当前记录(行)的第n个字段(列),$1代表第1列,$n代表第n列

FS          字段(列)的分隔符(默认是空格或制表符),可以使用-F选项自定义分隔符

OFS       输出字段(列)分隔符(用于格式化输出)

RS         记录(行)的分隔符,默认是换行符

ORS      输出记录(行)的分隔符,默认是换行符

NR         当前处理的行号,默认从1开始

NF         当前行的字段(列)数

awk运算符:

算术运算符:

+     加

–      减

*     乘

/      除

%    求余

^     求幂

++         自增,作为前缀或后缀

—           自减,作为前缀或后缀

注意,非数值的变量在使用算术运算符时会被自动转换为0

赋值运算符:

=

+=

-=

*=

/=

%=

^=

正则运算符:

~     匹配正则表达式

!~    不匹配正则表达式

逻辑运算符:

||     逻辑或 

&& 逻辑与

关系运算符:

<=

>=

!=

== 

其它运算符:

$            通过序号引用字段(列)

空格      字符串链接符

?:           三目运算符

ln           数组中是否存在某键值

awk正则表达式语法:

^            行首定位符

$            行尾定位符

.             匹配任意单个字符

*            匹配0个或多个前导字符(包括回车)

+            匹配1个或多个前导字符

?            匹配0个或1个前导字符

[]           匹配指定字符组内的任意一个字符/^[ab]

[^]          匹配不在指定字符组内的任意一个字符

()           子表达式

|             或

\             转义符

~            匹配条件语句

!~           不匹配条件语句

x{m}     x字符重复m次

x{m,}    x字符至少重复m次

X{m,n} x字符至少重复m次但不起过n次(需指定选项-posix或–re-interval)

awk打印(输出)命令:

print简单输出,用于输出字段(列)或文本,自动在每个字段(列)间插入空格,并在行末自动换行

printf提供了更多格式控制,可以指定字段的输出格式、宽度、对齐方式等。它类似于 C 语言的 printf 函数。若要输出换行,需要手动添加换行符\n

awk读取输入命令:

getline用于读取文件或命令的输出

awk内置函数:

toupper函数将所有小写字母转换成大写字母

length函数返回字符个数

system函数可以用来调用系统命令,虽然它不直接打印到终端,但可以执行其他命令并返回执行结果

awk自定义函数:

awk脚本中可以定义自己的函数,例如

function square(x) {

  return x * x

}

awk ‘{ print square($1) }’ file.txt

awk流程控制语句:

if-else 条件判断

while 和 do-while 循环

for 循环,包括 for-in 数组遍历

break 和 continue 控制循环的执行

exit 终止脚本执行

next 跳过当前行

return 函数返回值

三元条件表达式 ? :

awk数组:

awk 支持关联数组,这意味着数组的索引不仅可以是整数,也可以是字符串。awk 中的数组无需声明,也不需要定义大小,直接通过索引赋值即可使用。

    例:

1 输入和输出

$ echo “hello ” | awk ‘BEGIN{ print “start” } END{ print “end” }’

start

end

打印读取到的文本:

$ echo “hello ” | awk ‘BEGIN{ print “start” } {print} END{ print “end” }’

start

hello

end

打印整行:

$ echo “Hello World” | awk ‘{print $0}’

Hello World

打印特定字段(列):

$ echo “Alice 30” | awk ‘{print $1}’ # 输出第一列,awk默认以空白符分隔列

Alice

打印多个字段:

$ echo “Alice 30” | awk ‘{print $1, $2}’

Alice 30

简单格式化输出

$ echo “Alice 30” | awk ‘{printf “%s is %d years old\n”, $1, $2}’

Alice is 30 years old

指定输出列的宽度:

$ echo “Alice 30” | awk ‘{printf “%-10s %-5d\n”, $1, $2}’ # %-10s 表示左对齐,宽度为10;%-5d 表示左对齐,宽度为5

Alice      30

控制小数点位数:

$ echo “3.14159” | awk ‘{printf “%.2f\n”, $1}’

3.14

输出到文件或追加到文件:

awk 的 print 和 printf 命令都可以配合 >, >> 操作符,将内容输出到文件中:

  • 输出到文件:使用 > 将输出重定向到文件(会覆盖文件内容)。
  • 追加到文件:使用 >> 将输出追加到文件(不会覆盖已有内容)。

将输出写入文件:

$ echo “Alice 30” | awk ‘{print $1, $2 > “output.txt”}’ # 结果输出到 output.txt 文件中

将输出追加到文件:

$ echo “Bob 25” | awk ‘{print $1, $2 >> “output.txt”}’ # 输出会追加到 output.txt 文件末尾

重定向输出到标准错误stderr:

$ echo “Error message” | awk ‘{print $0 > “/dev/stderr”}’

输出多列时自定义列的分隔符:

$ echo -e “Alice 30\nBob 25″ | awk ‘BEGIN { OFS=” | ” } {print $1, $2}’

Alice | 30

Bob | 25

使用 getline 读取文件或命令的输出:

$ awk ‘BEGIN { while ((getline line < “input.txt”) > 0) print line }’ # 从 input.txt 文件中逐行读取并输出内容

2 普通变量的定义和使用

定义多个变量,然后打印它们:

$ echo|awk ‘{ a=”aa”; b=”bb”; c=”cc”; print a,b,c; }’

aa bb cc

print语句中的””起到拼接字符串的作用:

$ echo|awk ‘{ a=”aa”; b=”bb”; c=”cc”; print a” is “b” or “c; }’

aa is bb or cc

3 内置变量的使用

打印文件中的第一列和第三列:

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘{ print $1, $3 }’ test.txt

aa cc

11 33

xyz tt

$ awk ‘{ print $n }’ test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

打印第二列第一列并以,符号分隔:

$ awk ‘{print $2″,”$1}’  test.txt

bb,aa

22,11

yui,xyz

打印每行的行号和字段(列)数:

$ awk ‘{ print NR, NF }’ test.txt

1 5

2 5

3 3

4 外部变量的使用

$ a=100

$ b=100

$ echo |awk ‘{print v1*v2 }’ v1=$a v2=$b

10000

$ e=eee

$ echo |awk ‘{print e }’ e=$e

eee

在shell中,awk可以直接使用shell的环境变量。

5 awk运算符的使用

$ awk ‘BEGIN{a=”b”;print a,a++,a–,++a;}’

b 0 1 1

$ awk ‘BEGIN{a=”0″;print a,a++,a–,++a;}’

0 0 1 1

$ awk ‘BEGIN{a=7;b=2;print a/b;}’

3.5

$ awk ‘BEGIN{a=7;b=2;print a%b;}’

1

$ awk ‘BEGIN{a=7;b=2;print a^b;}’

49

$ awk ‘BEGIN{a=7;b=2;print a==b;}’

0

$ awk ‘BEGIN{a=7;b=2;print a=b;}’

2

打印第二列是22的行第一列:

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘($2 == 22) {print $1}’ test.txt

11

打印第3列的值大于66的行:

$ awk ‘$3 > 66’ test.txt

aa bb cc dd ee

xyz yui tt

? :三目运算符的使用示例:

$ awk ‘BEGIN{a=”b”;print a==”b”?”yes”:”no”}’

yes

6 正则表达式的使用

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

打印以a开头的行的第2列:

$ awk ‘/^a/{print $2}’ test.txt

bb

打印以a开头的行的第2列,并在第2列前加上aaa子串:

$ awk ‘/^a/{print “aaa”$2}’ test.txt

aaabb

打印第1列匹配xyz的行的第3列的值:

$ awk ‘$1~/xyz/ {print $3}’ test.txt

tt

如果变量a中包含test子串,那么打印yes:

$ echo|awk ‘BEGIN{a=”100testaaa”}a~/test/{print “yes”}’

yes

输出所有包含子串root的行:

awk ‘/root/{print $0}’ test.txt

7 awk内置函数的使用

toupper函数将所有小写字母转换成大写字母:

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘{print toupper($0)}’ test.txt

AA BB CC DD EE

11 22 33 44 55

XYZ YUI TT

length函数返回字符个数。打印长度为3个字符的第一列的内容:

$ awk ‘{if(length($1) == 3) print $1}’ test.txt

xyz

8 处理不同分隔符的文件

通过设置 -F 选项来指定输入的字段的分隔符。例如,对于以逗号分隔的 CSV 文件:

$ cat test.csv

ttc,yui,layui,tailwind

c,c++,go,java,python,php,js

apple,google,facebook,reddit,twitter,amazon

john@Ubuntu22-VirtualBox:~/test$ awk -F ‘,’ ‘{ print $1, $2 }’ test.csv

ttc yui

c c++

apple google

如果不使用-F ‘,’选项,就无法正确处理CSV文件:

$ awk ‘{ print $1, $2 }’ test.csv

ttc,yui,layui,tailwind

c,c++,go,java,python,php,js

apple,google,facebook,reddit,twitter,amazon

9 awk脚本的编写和使用

除了命令行上使用,我们也可以编写awk脚本文件,适合复杂的数据处理任务。例如,保存以下代码到 script.awk 文件中:

BEGIN { FS=”,”; OFS=” – ” }

{ print $1, $3 }

然后用 awk -f script.awk test.csv 来执行这个脚本:

$ awk -f script.awk test.csv

ttc – layui

c – go

apple – facebook

10 控制流程的使用

10.1 if-else 语句(条件判断)

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘{ if ($3 > 66) print $1, $3; else print $3, “not greater” }’ test.txt

aa cc

33 not greater

xyz tt

可以嵌套多个 if-else 语句:

awk ‘{ if ($1 > 10) print “Greater”; else if ($1 == 10) print “Equal”; else print “Smaller” }’ file.txt

10.2 while 语句(循环)

awk ‘{ i = 1; while (i <= NF) { print $i; i++ } }’ file.txt

10.3 do-while 语句(后测试循环)

do-while 循环会先执行一次循环体,然后检查条件是否为真:

awk ‘{ i = 1; do { print $i; i++ } while (i <= NF) }’ file.txt

10.4 for 语句(循环)

awk ‘{ for (i = 1; i <= NF; i++) print $i }’ file.txt

10.5 for-in遍历数组的所有索引

awk ‘{ for (i in arr) print arr[i] }’

10.6 break 语句(跳出循环)

awk ‘{ for (i = 1; i <= NF; i++) { if ($i == “stop”) break; print $i } }’ file.txt

10.7 continue 语句(继续下一次循环)

continue 语句用于跳过本次循环的剩余部分,并继续执行下一次循环:

awk ‘{ for (i = 1; i <= NF; i++) { if ($i == “skip”) continue; print $i } }’ file.txt

10.8 exit 语句(退出程序)

exit 语句用于终止 awk 脚本的执行,退出脚本时可以指定退出状态码:

awk ‘{ if ($1 == “exit”) exit; print $1 }’ file.txt

立即终止脚本的执行,剩余的行不会被处理。

可以在 END 块中使用 exit 返回状态码:

awk ‘END { if (NR == 0) exit 1 }’ file.txt

10.9 next 语句(跳到下一行)

next 语句用于跳过当前行的剩余操作,直接处理下一行:

awk ‘{ if ($1 == “skip”) next; print $1 }’ file.txt

10.10 return 语句(函数中使用)

return 语句用于在函数中返回值并退出函数:

function square(x) {

  return x * x

}

awk ‘{ print square($1) }’ file.txt

10.11 条件表达式(三元操作符)

awk ‘{ print ($1 > 10 ? “Greater” : “Smaller”) }’ file.txt

11 数组

11.1 定义和使用数组

awk 中通过赋值操作可以直接定义数组。例如:

awk ‘BEGIN { arr[1] = “apple”; arr[2] = “banana”; print arr[1], arr[2] }’

在这个例子中,arr[1] 和 arr[2] 定义了两个元素,分别存储 “apple” 和 “banana”。

使用字符串作为数组的索引:

awk ‘BEGIN { arr[“fruit”] = “apple”; print arr[“fruit”] }’

11.2 遍历数组

你可以使用 for-in 循环遍历数组中的所有元素,数组中的索引会被 for 循环访问:

awk ‘BEGIN {

    arr[1] = “apple”;

    arr[2] = “banana”;

    arr[3] = “cherry”;

    for (i in arr) {

        print i, arr[i];

    }

}’

这个例子会遍历数组 arr,输出数组的索引和对应的值。值得注意的是,awk 中 for-in 循环的遍历顺序并不保证是按索引的顺序,具体顺序取决于 awk 的实现。

11.3 删除数组元素

可以使用 delete 语句删除数组中的某个元素:

awk ‘BEGIN {

    arr[1] = “apple”;

    arr[2] = “banana”;

    delete arr[1];

    print arr[1];  # 输出为空,因为arr[1]已被删除

}’

delete 会将指定的数组元素完全移除,后续对该索引的访问将返回空值。

11.4 计算数组长度

awk 本身没有直接的函数来计算数组的长度,但你可以通过遍历数组来计算元素个数。例如:

awk ‘BEGIN {

    arr[1] = “apple”;

    arr[2] = “banana”;

    arr[3] = “cherry”;

    count = 0;

    for (i in arr) {

        count++;

    }

    print “Array length:”, count;

}’

11.5 多维数组

虽然 awk 本质上是支持一维数组,但可以通过组合索引来实现多维数组的效果。你可以使用多个索引作为键,例如:

awk ‘BEGIN {

    arr[1,1] = “apple”;

    arr[1,2] = “banana”;

    arr[2,1] = “cherry”;

    print arr[1,1];  # 输出apple

    print arr[1,2];  # 输出banana

    print arr[2,1];  # 输出cherry

}’

这里 arr[1,1] 和 arr[1,2] 类似于二维数组的定义,逗号 , 将多个索引组合在一起。

11.6 数组的默认值

在 awk 中,未被初始化的数组元素会默认返回空字符串或 0,具体取决于如何使用。例如:

awk ‘BEGIN {

    print arr[1];  # 输出为空,因为arr[1]未被初始化

}’

如果试图对一个未初始化的数组元素进行运算操作,它将被视为 0。

12 综合实例

获取enp0s3网卡的IP地址:

$ ifconfig enp0s3|awk ‘BEGIN{FS=”[[:space:]:]+”} NR==2{print $3}’

10.0.2.15

打印当前目录下的子目录和文件的总字节数,以MB为单位:

$ ls -alh|awk ‘BEGIN{size=0;} {size=size+$5;} END{print “total size is “,size/1024/1024,”MB”}’

total size is  0.000601768 MB

sed流编辑器

功能说明:sed是一种流编辑器,能够从文件或输入流中逐行读取文本,并根据用户指定的模式或命令对文本进行编辑,之后将结果输出到屏幕或文件中。配合正则表达式使用功能强大。

语  法:

sed [options] ‘command’ file(s)

sed [options] -f scriptfile file(s)

补充说明:sed先把当前处理的一行文本存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区的内容,完成后输出到终端,接着处理下一行文本。文件内容并没有被改变,除非使用-i选项。sed主要用来编辑一个或多个文本文件,简化对文本文件的反复操作或者用来编写文本转换程序等。sed功能同awk类似,差别在于sed更加简单,对列处理的功能要差一些,awk功能复杂,对列处理的功能比较强大。

   项:

-e    以指定的指令来处理输入的文本文件

-n    取消默认输出(如果和p命令同时使用只会打印发生改变的行)

-h    显示帮助信息

-V   显示版本信息

参  数:

command     命令

file(s)           一个或多个文本文件

scriptfile       存放了命令的脚本文件

   作:

a     在当前行下面插入文本

i      在当前行上面插入文本

c     把选定的行改为新的文本

d     删除选择的行

D    删除模板块的第一行

s      替换指定字符

h     拷贝模板块的内容到内存中的缓冲区

H    追加模板块的内容到内存中的缓冲区

g     获得内存缓冲区的内容,并替代当前模板块中的文本

G    获得内存缓冲区的内容,并追加到当前模板块文本的后面

l      列出不能打印字符的清单

L  列出不能打印字符的清单,该选项用于非ASCII字符

n     读取下一个输入行,用下一个命令处理新的行而不是用第一个命令

N    追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码

p     打印匹配的行

P     打印模板的第一行

q     退出sed

b     lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾

r      file 从文件中读行

t      label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾

T     label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾

w    file 写并追加模板块到文件的末尾

W   file 写并追加模板块的第一行到file末尾

!      表示后面的命令对所有没有被选定的行发生作用

=     打印当前行号码

#     把注释扩展到下一个换行符以前

替换命令:

g     表示行内全面替换(全局替换配合s命令使用)

p     表示打印行

w    表示把行写入一个文件

x     表示互换模板块中的文本和缓冲区中的文本

y     表示把一个字符翻译为另外的字符(但是不用于正则表达式)

1     子串匹配的标记 

&    已匹配字符串的标记

sed的基本正则表达式(BREBasic Regular Expression)语法:

^     匹配行开始

$     匹配行结束

.      匹配一个非换行符的任意字符

*     匹配0个或多个字符

[]    匹配指定范围内的一个字符

[^]   匹配不在指定范围内的一个字符

(..)  匹配子串

&    保存搜索字符用来替换其他字符

<     匹配单词的开始

>     匹配单词的结束

x{m}     重复字符x,m次

x{m,}    重复字符x,至少m次

x{m,n}  重复字符x,至少m次,不多于n次

使用 \< 来匹配单词开头,\> 来匹配单词结尾

sed的扩展正则表达式(EREExtended Regular Expression)语法:

\b    匹配单词边界,但默认的sed正则表达式语法不支持 \b

+     匹配一个或多个字符

    例:

1 打印输出

只输出指定行号的行:

$ cat test.txt

abcd 12345

b

c

d

e

输出第1行和最后一行:

$ sed -n ‘1p;$p’ test.txt

abcd 12345

e

输出第2行和第3行:

$ sed -n ‘2p;3p’ test.txt

b

c

输出第2行、第3行和第4行:

$ sed -n ‘2p;3p;4p’ test.txt

b

c

d

其中-n选项取消默认输出,p命令只打印输出指定行号的行。

只输出奇数行号的行:

$ sed -n ‘p;n’ test.txt

abcd 12345

c

e

只输出偶数行号的行:

$ sed -n ‘n;p’ test.txt

b

d

从第1行开始隔行输出:

$ sed -n ‘1~2p’ test.txt

abcd 12345

c

e

从第2行开始隔行输出:

john@Ubuntu22-VirtualBox:~/test$ sed -n ‘2~2p’ test.txt

b

d

打印匹配字符串行的下一行:

$ sed -n ‘/^b/{n;p}’ test.txt

c

$ awk ‘/^b/{getline; print}’ test.txt

c

使用l 和 L 动作打印输出行内容,并以不同的方式显示控制字符(如不可打印字符、换行符等):

  • l 动作:显示行内容,并将非打印字符(如制表符、换行符)以可视化符号显示,适用于处理 ASCII 文本。
  • L 动作:类似于 l,但专为处理多字节字符(如 UTF-8)设计,适合包含国际化字符的文本。

示例1

$ cat test.txt

ab

c     d 12345

b

c

d

e

执行 l 动作后,sed 会将每一行的内容打印出来,并将非打印字符(如换行、制表符等)显示为可视符号:

$ sed -n ‘l’ test.txt

ab$

c\td 12345$

b$

c$

d$

e$

其中

  • \t 表示制表符,\n 表示换行符。
  • $ 表示行的结尾,通常被 sed 用来可视化显示每行的结束。

示例2

$ cat test1.txt

Hello 世界

与 l 动作不同,L 更适用于处理多字节字符,特别是在显示非 ASCII 字符时:

$ sed -n ‘L’ test1.txt

Hello 世$

界$

其中多字节字符(如中文字符“世界”)会被正确显示为两行,其中 世 和 界 分别占用一行,这在某些编辑场景下可能是期望的效果。

注意,低版本sed不支持L选项!

2 删除

删除空行:

sed ‘/^$/d’ filename

删除第二行:

sed ‘2d’ filename

删除第二直到未尾所有行:

sed ‘2, $d’ filename

删除最后一行:

sed ‘$d’ filename

删除以test开头行:

sed ‘/^test/’d filename

3 简单的匹配和替换

echo “hello world” |sed ‘s/ /-/g’

hello-world 

从第一个空格开始把空格符号全局替换成’-‘符号,只不过”hello world”文本中只有一个空格。

匹配一个完整的单词并替换:

$ echo “hello world” | sed ‘s/[a-zA-Z0-9_][a-zA-Z0-9_]*/replacement/g’

replacement replacement

其中

  • [a-zA-Z0-9_] 匹配一个字母、数字或下划线。
  • [a-zA-Z0-9_]* 匹配零个或多个后续的字母、数字或下划线

在某些支持扩展正则表达式的工具(如 sed -E 或 grep -E),你可以直接使用 + 来表示一个或多个字符:

$ echo “hello world” | sed -E ‘s/[a-zA-Z0-9_]+/replacement/g’

replacement replacement

4 进阶的匹配和替换

$ echo “hello world” | sed ‘s/[a-zA-Z0-9_][a-zA-Z0-9_]*/[&]/g’

[hello] [world]

其中&表示匹配到的子串。

通过正则表达式分组和替换实现反转输出一个字符串中的空格分隔的子串:

$ echo “abc def ghi” | sed ‘s/\([a-zA-Z]*\) \([a-zA-Z]*\) \([a-zA-Z]*\)/\3 \2 \1/’

ghi def abc

如果有更多的子串,使用 sed 进行手动反转就会变得非常复杂,因为 sed 的捕获组数量有限(通常只能捕获到9个组,即 \1 到 \9)。如果需要反转更多子串,建议使用更强大的文本处理工具,如 awk 或 perl。例如:

$ echo “abc def ghi jkl mno” | awk ‘{ for (i=NF; i>0; i–) printf(“%s “, $i); print “” }’

mno jkl ghi def abc

其中

  • NF 表示字段数量,$i 表示第 i 个字段。
  • for (i=NF; i>0; i–) 从最后一个字段开始向前输出,直到第一个字段。

5 多点编辑功能

多点编辑功能可以通过 -e 选项来实现。-e 选项允许你在同一个 sed 命令中执行多个编辑操作。每个编辑命令都可以通过 -e 传递,这样你可以在一次执行中对文件或输入流进行多种编辑操作,而不需要多次调用 sed。

基本语法:

sed -e ‘command1’ -e ‘command2’ … filename

或者将多个 -e 选项合并为一个(不使用 -e 的情况下也可以):

sed ‘command1; command2’ filename

示例1 一次完成两个替换操作

$ cat example.txt

Hello World

This is a test

Goodbye World

$ sed -e ‘s/Hello/Hi/’ -e ‘s/Goodbye/Farewell/’ example.txt

Hi World

This is a test

Farewell World

你也可以不用多次使用 -e,而是通过分号分隔多个命令:

sed ‘s/Hello/Hi/; s/Goodbye/Farewell/’ example.txt

示例2 删除和替换操作的组合

假设你想要删除文件中的第 2 行,并将 “World” 替换为 “Everyone”。你可以通过以下命令来实现:

$ cat example.txt

Hello World

This is a test

Goodbye World

$ sed -e ‘2d’ -e ‘s/World/Everyone/’ example.txt

Hello Everyone

Goodbye Everyone

6 读一个文本文件

sed默认操作就是读取文本文件内容并对其进行处理。

示例1 读取并打印文件内容

$ cat input.txt

Hello World

This is a test

Goodbye World

$ sed ” input.txt

Hello World

This is a test

Goodbye World

示例2 读取并替换文件内容

假设你想将 World 替换为 Everyone,可以这样做:

$ sed ‘s/World/Everyone/’ input.txt

Hello Everyone

This is a test

Goodbye Everyone

7 使用r动作读取文件并插入内容

r 动作用于将外部文件的内容读入并插入到当前处理的文本中。指定一个文件,sed 会将该文件的内容插入到匹配的行之后。语法:

sed ‘/pattern/r file_to_read’ input_file

其中

  • /pattern/:匹配模式行(可选),即插入文件内容的位置。
  • file_to_read:你想要读取的文件。
  • input_file:原始文件,sed 将对其进行处理。

示例1

假设有一个文件 data.txt,内容如下:

Line 1

Line 2

Line 3

还有另一个文件 extra.txt,内容如下:

Extra content 1

Extra content 2

如果你想在 data.txt 的匹配 Line 2的每一行后插入 extra.txt 的内容,可以使用以下命令:

sed ‘/Line 2/r extra.txt’ data.txt

输出结果:

Line 1

Line 2

Extra content 1

Extra content 2

Line 3

8 写一个文本文件

为了将 sed 的输出保存到一个新的文件,或者覆盖现有的文件,可以使用输出重定向或 -i 选项(用于直接修改文件)。

示例1 使用输出重定向写入文件

假设你想将替换后的内容写入到一个新文件 output.txt:

$ cat input.txt

Hello World

This is a test

Goodbye World

$ sed ‘s/World/Everyone/’ input.txt > output.txt

$ cat output.txt

Hello Everyone

This is a test

Goodbye Everyone

以上将 sed 的输出结果重定向到 output.txt,不会改变原始文件 input.txt 的内容。

示例2 使用 -i 选项直接修改文件本身

如果你想直接修改 input.txt 文件本身,可以使用 -i 选项:

$ sed -i ‘s/World/Everyone/’ input.txt

$ cat input.txt

Hello Everyone

This is a test

Goodbye Everyone

示例3 在文件中添加内容

你也可以通过 sed 来插入或添加内容,并保存到文件中。假设你想在input.txt文件的第 1 行之前插入一行新文本 “ID: 1234″,并将其保存到原文件中:

$ cat input.txt

Hello Everyone

This is a test

Goodbye Everyone

$ sed -i ‘1i ID: 1234’ input.txt

$ cat input.txt

ID: 1234

Hello Everyone

This is a test

Goodbye Everyone

其中1i表示在第 1 行之前插入一行新文本。

9 使用w 动作写入文件

w 动作用于将匹配的行或处理后的内容写入到一个指定的文件。它通常用于保存处理过的内容到新的文件,而不是修改原文件。语法:

sed ‘/pattern/w output_file’ input_file

其中

  • /pattern/:匹配模式行,符合该模式的行会被写入指定的文件。
  • output_file:写入的目标文件,如果文件不存在,sed 会自动创建它。
  • input_file:原始文件,sed 将对其进行处理。

示例1

假设有一个文件 data.txt,内容如下:

Line 1

Line 2

Line 3

你想将匹配 Line 2 的行写入到文件 output.txt 中,可以使用以下命令:

sed ‘/Line 2/w output.txt’ data.txt

执行该命令后,output.txt 文件将包含以下内容:

Line 2

示例2 结合 r 和 w

假设你想读取外部文件的内容并插入到某个模式之后,同时将匹配的行写入到另一个文件中,可以这样做:

sed ‘/Line 2/r extra.txt; /Line 2/w output.txt’ data.txt

其中

  • /Line 2/r extra.txt:在匹配到 Line 2 的地方插入 extra.txt 文件的内容。
  • /Line 2/w output.txt:将匹配的 Line 2 行写入到 output.txt。

od将指定文件内容以八进制数、十进制数、十六进制数、浮点数或ASCII字符的方式输出到标准输出显示

功能说明:od将指定文件内容以八进制数、十进制数、十六进制数、浮点数或ASCII字符方式输出到标准输出显示,并且最左边一列显示字节地址偏移量,从0开始

语  法:od [OPTION…] [FILE…]

补充说明:od命令默认的显示方式是八进制数。常见的文件为文本文件和二进制文件。od命令通常用于显示或查看文件中不能直接显示在终端的字符,主要用来查看保存在二进制文件中的数据,按照指定格式解释文件中的数据并输出,不管是IEEE754格式的浮点数还是ASCII码,od命令都能按照需求输出它们的值。大家也可以了解一下hexdump命令,默认以十六进制数输出数据,但感觉hexdump命令没有od命令强大。

          项:

-A RADIX或–address-radix=RADIX        选择以何种基数表示字节地址偏移量。默认以八进制数显示

-j BYTES或–skip-bytes=BYTES               跳过指定数目的字节

-N BYTES或–read-bytes=BYTES             输出指定字节个数

-S [BYTES]或–strings[=BYTES]               输出长度不小于指定字节数的字符串,BYTES 缺省值为 3

-v或–output-duplicates                               输出时不省略重复的数据

-w [BYTES]或–width[=BYTES]                设置每行最多显示的字节个数,BYTES 缺省为 32 字节

-t TYPE或–format=TYPE                          指定输出格式,格式包括 a、c、d、f、o、u 和 x,各含义如下:

  • a:具名字符。比如换行符显示为 nl
  • c:可打印字符或反斜杠表示的转义字符。比如换行符显示为 \n
  • d[SIZE]:SIZE 字节组成一个有符号十进制整数。SIZE 缺省值为 sizeof(int)
  • f[SIZE]:SIZE 字节组成一个浮点数。SIZE 缺省为 sizeof(double)
  • o[SIZE]:SIZE 字节组成一个八进制整数。SIZE 缺省为 sizeof(int)
  • u[SIZE]:SIZE 字节组成一个无符号十进制整数。SIZE 缺省为 sizeof(int)
  • x[SIZE]:SIZE 字节组成一个十六进制整数。SIZE 缺省为 sizeof(int)

SIZE可以1数字,也可以是大写字母。如果 TYPE 是 [doux] 中的一个,那么SIZE 可以是C = sizeof(char),S = sizeof(short),I = sizeof(int),L = sizeof(long)。如果 TYPE 是 f,那么 SIZE 可以是 F = sizeof(float),D = sizeof(double) ,L = sizeof(long double)

–help           显示帮助信息

–version       显示版本信息

参  数:

FILE…         要显示内容数据的一个或多个文件

   例:

实例1
$ cat test.txt
abcd 12345
$ od test.txt 
0000000 061141 062143 030440 031462 032464 000012
0000013
输出中的第一列是字节地址偏移量,默认以八进制数显示。

实例2
设置第一列的字节偏移地址以十进制显示:
$ od -Ad test.txt 
0000000 061141 062143 030440 031462 032464 000012
0000011

实例3
不显示第一列偏移地址:
$ od -An test.txt 
 061141 062143 030440 031462 032464 000012

实例4
以十六进制数输出,默认以四字节为一组(一列)显示:
$ od -tx test.txt 
0000000 64636261 33323120 000a3534
0000013

实例5
以十六进制数输出,每列输出1个字节:
$ od -tx1 test.txt
0000000 61 62 63 64 20 31 32 33 34 35 0a
0000013

实例6
以具名字符显示ASCII字符:
$ od -ta test.txt
0000000   a   b   c   d  sp   1   2   3   4   5  nl
0000013
以可打印字符或反斜杠表示的转义字符显示ASCII字符:
$ od -tc test.txt
0000000   a   b   c   d       1   2   3   4   5  \n
0000013

实例7
以十六进制数显示的同时显示原字符:
$ od -tcx1 test.txt
0000000   a   b   c   d       1   2   3   4   5  \n
         61  62  63  64  20  31  32  33  34  35  0a
0000013

实例8
指定每行显示512字节:
$ od -w8 -tc test.txt
0000000   a   b   c   d       1   2   3
0000010   4   5  \n
0000013

实例9
实现od命令输出时去除列与列之间的空格符的方法:
1	使用-An不输出偏移地址;
2 使用-v输出时不省略重复的数据;
3 使用-tx1以单个字节为一组按照十六进制输出,-w1每列输出一个字节;
4 最后通过管道传递给 awk 的标准输入,通过awk不换行输出所有行,拼接为一行输出。
$ od -An -w1 -tx1 test.txt|awk '{for(i=1;i<=NF;++i){printf "%s",$i}}'
616263642031323334350a

Linux命令xargs给其他命令传递参数

xargs给其他命令传递参数

功能说明:给其他命令传递参数,是构建单行命令的重要组件之一。

语  法:xargs [OPTIONS] [COMMAND]

补充说明:xargs可以将stdin中以空格或换行符进行分隔的数据,形成以空格分隔的参数(arguments),传递给其他命令。注意,因为以空格作为分隔符,所以有一些文件名或者其他意义的字符串内含有空格的时,xargs可能会误判。

    项:

-0, –null       默认选项。如果输入的stdin含有特殊字符,例如反引号 `、反斜杠 \、空格等字符时,xargs将它还原成一般字符。

-a, –arg-file=FILE    从指定的文件FILE中读取输入内容而不是从stdin

-d, –delimiter=DEL  指定xargs处理输入内容时的分隔符。xargs处理输入内容时默认使用空格和换行符作为分隔符,输出arguments时按空格分隔

-E EOF_STR      EOF_STR的意思是end of file string,表示输入结束的字符串。如果没有EOF_STR则表示输入没有结束符。注意,结束标识符必须要是单独的字段,即以空格或者换行符分隔开来的字段。

-e, –eof[=EOF_STR]       作用等同于-E选项。该选项不符合POSIX标准且EOF_STR是可选的。与-E选项不同时,以-E选项为准。

-I REPLACE_STR    将xargs输出的每一项参数单独赋值给后面的命令,参数需要用指定的替代字符串REPLACE_STR代替。REPLACE_STR可以使用{}、$、@ 等符号,其主要作用是当xargs命令后有多个参数时,用于调整参数位置。例如备份以 txt 为后缀的文件:find . -name “*.txt” | xargs -I {}  cp {} /tmp/{}.bak

-i, –replace[=REPLACE_STR]     作用同 -I 选项,REPLACE_STR是可选的,缺省为 {}。建议使用 -I 选项,因为其符合POSIX标准,而该选项不符合POSIX标准。

-L MAX_LINES        限定最大输入行数。隐含了 -x 选项。

-l, –max-lines[=MAX_LINES]     作用同 -L 选项,MAX_LINES 是可选的,缺省为1。建议使用 -L 选项,因为其符合 POSIX 标准,而该选项不符合POSIX标准。

-n, –max-args=MAX_ARGS         表示命令在执行的时候一次使用参数的最大个数。

-o, –open-tty       在执行命令之前,在子进程中重新打开stdin作为/dev/TTY。如果你希望xargs运行交互式命令行应用程序,这是非常有用的。

-P, –max-procs=MAX_PROCS     每次运行的最大进程数,默认值为1。如果MAX_PROCS为 0,xargs将一次运行尽可能多的进程。一般和-n或-L选项一起使用。

-p, –interactive   每次执行一个argument的时候询问一次用户。

–process-slot-var=NAME       将指定的环境变量设置为每个正在运行的子进程中的唯一值。一旦子进程退出,将重用该值。例如,这可以用于初始负荷分配方案。

-r, –no-run-if-empty         默认选项。当 xargs 的输入为空的时候则停止xargs,不用再去执行后面的命令了。

-s, –max-chars=MAX_CHARS     命令行的最大字符数,指的是xargs后面那个命令的最大字符个数,包括命令字符串本身、空格符和换行符。每个参数单独传入xargs后面的命令。

–show-limits      显示操作系统对命令行长度的限制。

-t, –verbose     先打印要执行的命令到标准错误输出,然后再执行。

-x, –exit              配合 -s 使用,当命令行字符数大于 -s 指定的数值时,退出 xargs。

–help           显示帮助信息并退出。

–version       显示版本信息并退出

    数:

COMMAND       命令字符串

    例:

实例1
很多命令不支持使用管道|来传递参数,此时可以使用xargs来传递参数,例如常用的ls命令:
 # 错误示例,因为标准输入不能作为ls的参数
find /sbin -perm +700 | ls -l
# 正确示例,使用xargs来传递参数
find /sbin -perm +700 | xargs ls -l

实例2
显示操作系统对命令行长度的限制信息:
$ xargs --show-limits
您的环境变量占有 2226 个字节
此系统的参数长度 POSIX 上限: 2092878
所有系统中所允许的最小参数长度 POSIX 上限: 4096
我们实际能用的最大命令长度: 2090652
我们实际能用的命令缓冲区的大小: 131072
最大并行数(--max-procs 不得大于该值):2147483647

设置命令行的最大字符数:
$ echo "01234 56789" | xargs -t -s 11
echo 01234
01234
echo 56789
56789

实例3
将 Shell 的反引号特殊字符还原为一般字符:
$ echo '`0123`4 56789' | xargs -t echo
echo '`0123`4' 56789
`0123`4 56789
其中-t选项的作用是,让xargs先打印要执行的命令到标准错误输出,然后再执行。因为反引号在 Shell 中会将 01234 作为一个命令来执行,但是 01234 不是一个命令。如果直接执行如下命令会报错:
$ echo `0123`4 56789
0123:未找到命令
4 56789

实例4
设置 xargs 读入参数时的结束标识为逗号",":
$ echo 01234 , 56789 | xargs -E ","
01234
注意,结束标识符必须要是单独的字段,即以空格或者换行符分隔开来的字段。

实例5
使用 rm、mv 等命令同时操作多个文件时,有时会报 “argument list too long” 参数列表过长的错误,此时可以使用 xargs 来解决这个错误。xargs 将标准输入的字符串分隔后,作为参数传递给后面的命令。例如:
# 给当前目录的所有文件添加后缀名
ls | xargs -t -i mv {} {}.bak
# 选择符合条件的文件
ls | grep -E "201701|201702|201703" | xargs -I {} mv {} {}.bak

实例6
设置标准输入中每次多少行作为xargs后面的命令的参数:
$ echo -e "01234\n56789\n01234" | xargs -t -L 2 echo
echo 01234 56789 
01234 56789
echo 01234 
01234
默认情况下-L选项的值是1,也就是将标准输入中所有行的归并到一行一次性传给xargs后面的命令执行:
$ echo -e "01234\n56789\n01234" | xargs -t echo
echo 01234 56789 01234
01234 56789 01234

实例7
将文件内容以空格分隔合并为一行输出:
# 列出文件内容
$ cat test.txt
a b c d e
f g h i j 
k l m n o
# 多行输入合并为一行输出
$ cat test.txt | xargs
a b c d e f g h i j k l m n o
# 相当于
$ cat test.txt | xargs echo
a b c d e f g h i j k l m n o

实例8
与ps、grep、awk和kill结合,强制终止指定进程:
$ ps -ef | grep spp | awk '{printf "%s ",$2}' | xargs kill -9
1
其中
ps -ef|grep spp用于查找进程名字或描述信息中包含 spp 子字符串的进程
awk '{printf "%s ",$2}将目标进程 ID 打印输出
xargs kill -9则将目标进程 ID 作为参数传递给kill -9用于杀死进程