0%

linux | 文本处理

这里介绍在 linux 中的文本处理方法。

  • awk
  • sed
  • grep
  • wc

wc


Linux wc命令用于计算字数。

利用wc指令我们可以计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为 -,则wc指令会从标准输入设备读取数据。

wc [-clw][--help][--version][文件...]
  • -c--bytes--chars 只显示Bytes数。
  • -l--lines 只显示行数。
  • -w--words 只显示字数。
  • --help 在线帮助。
  • --version 显示版本信息。

实例

在默认的情况下,wc将计算指定文件的行数、字数,以及字节数。使用的命令为:

1
wc testfile

先查看testfile文件的内容,可以看到:

$ cat testfile  
Linux networks are becoming more and more common, but scurity is often an overlooked  
issue. Unfortunately, in today’s environment all networks are potential hacker targets,  
fro0m tp-secret military research networks to small home LANs.  
Linux Network Securty focuses on securing Linux in a networked environment, where the  
security of the entire network needs to be considered rather than just isolated machines.  
It uses a mix of theory and practicl techniques to teach administrators how to install and  
use security applications, as well as how the applcations work and why they are necesary. 

使用 wc统计,结果如下:

$ wc testfile           # testfile文件的统计信息  
3 92 598 testfile       # testfile文件的行数为3、单词数92、字节数598 

其中,3 个数字分别表示testfile文件的行数、单词数,以及该文件的字节数。

如果想同时统计多个文件的信息,例如同时统计testfiletestfile_1testfile_2,可使用如下命令:

1
wc testfile testfile_1 testfile_2   #统计三个文件的信息

输出结果如下:

1
2
3
4
5
$ wc testfile testfile_1 testfile_2  #统计三个文件的信息  
3 92 598 testfile #第一个文件行数为3、单词数92、字节数598
9 18 78 testfile_1 #第二个文件的行数为9、单词数18、字节数78
3 6 32 testfile_2 #第三个文件的行数为3、单词数6、字节数32
15 116 708 总用量 #三个文件总共的行数为15、单词数116、字节数708

统计进程行数

1
ps -e | wc -l

sed


ps: 该命令的执行方式在 linux 中和 MacBook 表现不一样。

Linux sed 命令是利用脚本来处理文本文件。

sed 可依照脚本的指令来处理、编辑文本文件。

Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

sed [-hnV][-e<script>][-f<script文件>][文本文件]
  • -e<script>--expression=<script> 以选项中指定的script来处理输入的文本文件。
  • -f<script文件>--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
  • -h--help 显示帮助。
  • -n--quiet--silent 仅显示script处理后的结果。
  • -V--version 显示版本信息。

动作说明:

  • a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
  • c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
  • d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
  • i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
  • p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
  • s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

实例

testfile文件的第四行后添加一行,并将结果输出到标准输出,在命令行提示符下输入如下命令:

sed -e 4a\newLine testfile

sed -e 没有 -e 也行啦!同时也要注意的是,sed 后面接的动作,请务必以 '' 两个单引号括住喔!

sed '4a newLine' testfile # 效果和上面相同

以行为单位的新增/删除

/etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除!

nl /etc/passwd | sed '2,5d'

只要删除第 2

nl /etc/passwd | sed '2d' 

要删除第 3 到最后一行

nl /etc/passwd | sed '3,$d' 

在第二行前写东西

nl /etc/passwd | sed '2i drink tea' 

增加多行

nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'

命令行中有 \ 的时候,指可以继续向下写,每一行之间都必须要以反斜杠『 \ 』来进行新行的添加喔!

具体到某一段添加

nl test | sed '/i21/a\55'

在行为 i21 后面添加 55

以行为单位的替换与显示

将第2-5行的内容取代成为No 2-5 number呢?

nl /etc/passwd | sed '2,5c No 2-5 number'

透过这个方法我们就能够将数据整行取代了!

仅列出 /etc/passwd 文件内的第 5-7

nl /etc/passwd | sed -n '5,7p'

数据的搜寻并显示

搜索 /etc/passwdroot关键字的行

nl /etc/passwd | sed '/root/p'

如果root找到,除了输出所有行,还会输出匹配行。

使用-n的时候将只打印包含模板的行。

比如,一个文件 test 内容如下

1
2
3
4
5
i21
213
qwe
231
da

执行

nl test | sed '/21/p'

输出

1
2
3
4
5
6
7
1	i21
1 i21
2 213
2 213
3 qwe
4 231
5 da

执行

nl test | sed -n '/21/p'

输出

1
2
1	i21
2 213

数据的搜寻并删除

删除/etc/passwd所有包含root的行,其他行输出

nl /etc/passwd | sed  '/root/d'

数据的搜寻并执行命令

搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把bash替换为blueshell,再输出这行:

nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p;q}'   

最后的q是退出。

这个命令我没执行成功。

数据的搜寻并替换

除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并取代。基本上 sed 的搜寻与替代的与 vi 相当的类似!他有点像这样:

sed 's/要被取代的字串/新的字串/g'

先观察原始信息,利用 /sbin/ifconfig 查询 IP

命令

ifconfig eno1
1
2
3
4
5
6
7
8
9
eno1      Link encap:Ethernet  HWaddr ac:1f:6b:26:4d:fc  
inet addr:219.244.171.32 Bcast:219.244.171.127 Mask:255.255.255.128
inet6 addr: fe80::3fb4:8d96:de56:9324/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:291344722 errors:0 dropped:0 overruns:147 frame:0
TX packets:217593618 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:356581381856 (356.5 GB) TX bytes:168166493142 (168.1 GB)
Memory:fb120000-fb13ffff

命令

/sbin/ifconfig eno1 | grep 'inet addr'

输出

1
inet addr:219.244.171.32  Bcast:219.244.171.127  Mask:255.255.255.128

命令

/sbin/ifconfig eno1 | grep 'inet addr'|sed 's/^.*addr://g'

输出

1
219.244.171.32  Bcast:219.244.171.127  Mask:255.255.255.128

命令

/sbin/ifconfig eno1 | grep 'inet addr'|sed 's/^.*addr://g' | sed 's/Bca.*$//g'

输出

1
219.244.171.32

多点编辑

一条sed命令,删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell

nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'

直接修改文件内容

利用 sedregular_express.txt 内每一行结尾若为 . 则换成 !

sed -i 's/\.$/\!/g' regular_express.txt

利用 sed 直接在 regular_express.txt 最后一行加入 # This is a test:

sed -i '$a # This is a test' regular_express.txt

由於 $ 代表的是最后一行,而 a 的动作是新增,因此该文件最后新增 # This is a test!

sed-i 选项可以直接修改文件内容,这功能非常有帮助!举例来说,如果你有一个 100 万行的文件,你要在第 100 行加某些文字,此时使用 vim 可能会疯掉!因为文件太大了!那怎办?就利用 sed 啊!透过 sed 直接修改/取代的功能,你甚至不需要使用 vim 去修订!


grep


grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

选项 作用
-a 不要忽略二进制数据。
-A <显示列数> 除了显示符合范本样式的那一行之外,并显示该行之后的内容。
-b 在显示符合范本样式的那一行之外,并显示该行之前的内容。
-c 计算符合范本样式的列数。
-C <显示列数>或-<显示列数> 除了显示符合范本样式的那一列之外,并显示该列之前后的内容。
-d <进行动作> 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。
-e <范本样式> 指定字符串作为查找文件内容的范本样式。
-E 将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式。
-f <范本文件> 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式。
-F 将范本样式视为固定字符串的列表。
-G 将范本样式视为普通的表示法来使用。
-h 在显示符合范本样式的那一列之前,不标示该列所属的文件名称。
-H 在显示符合范本样式的那一列之前,标示该列的文件名称。
-i 忽略字符大小写的差别。
-l 列出文件内容符合指定的范本样式的文件名称。
-L 列出文件内容不符合指定的范本样式的文件名称。
-n 在显示符合范本样式的那一列之前,标示出该列的编号。
-q 不显示任何信息。
-R/-r 此参数的效果和指定“-d recurse”参数相同。
-s 不显示错误信息。
-v 反转查找。
-w 只显示全字符合的列。
-x 只显示全列符合的列。
-y 此参数效果跟“-i”相同。
-o 只输出文件中匹配到的部分。

在文件中搜索一个单词,命令会返回一个包含“match_pattern”的文本行:

grep match_pattern file_name
grep "match_pattern" file_name

在多个文件中查找:

grep "match_pattern" file_1 file_2 file_3 ...

输出除之外的所有行 -v 选项:

grep -v "match_pattern" file_name

标记匹配颜色 --color=auto 选项:

grep "match_pattern" file_name --color=auto

使用正则表达式 -E 选项:

grep -E "[1-9]+"
或
egrep "[1-9]+"

只输出文件中匹配到的部分 -o 选项:

echo this is a test line. | grep -o -E "[a-z]+\."
line.

echo this is a test line. | egrep -o "[a-z]+\."
line.

统计文件或者文本中包含匹配字符串的行数 -c 选项:

grep -c "text" file_name

输出包含匹配字符串的行数 -n 选项:

grep "text" -n file_name    
或
cat file_name | grep "text" -n
#多个文件
grep "text" -n file_1 file_2

打印样式匹配所位于的字符或字节偏移:

echo gun is not unix | grep -b -o "not"
7:not

一行中字符串的字符便宜是从该行的第一个字符开始计算,起始值为 0。选项 -b -o 一般总是配合使用。

搜索多个文件并查找匹配文本在哪些文件中:

grep -l "text" file1 file2 file3...

grep递归搜索文件

在多级目录中对文本进行递归搜索:

grep "text" . -r -n
# .表示当前目录。

忽略匹配样式中的字符大小写:

echo "hello world" | grep -i "HELLO"
hello

选项 -e 制动多个匹配样式:

echo this is a text line | grep -e "is" -e "line" -o
is
line

#也可以使用-f选项来匹配多个样式,在样式文件中逐行写出需要匹配的字符。
cat patfile
aaa
bbb

echo aaa bbb ccc ddd eee | grep -f patfile -o

grep搜索结果中包括或者排除指定文件:

#只在目录中所有的.php和.html文件中递归搜索字符"main()"
grep "main()" . -r --include *.{php,html}

#在搜索结果中排除所有README文件
grep "main()" . -r --exclude "README"

#在搜索结果中排除filelist文件列表里的文件
grep "main()" . -r --exclude-from filelist

使用0值字节后缀的grepxargs

#测试文件:
echo "aaa" > file1
echo "bbb" > file2
echo "aaa" > file3

grep "aaa" file* -lZ | xargs -0 rm

#执行后会删除file1和file3,grep输出用-Z选项来指定以0值字节作为终结符文件名(\0),xargs -0 读取输入并用0值字节终结符分隔文件名,然后删除匹配文件,-Z通常和-l结合使用。

grep静默输出:

grep -q "test" filename

#不会输出任何信息,如果命令运行成功返回0,失败则返回非0值。一般用于条件测试。

打印出匹配文本之前或者之后的行:

#显示匹配某个结果之后的3行,使用 -A 选项:
seq 10 | grep "5" -A 3
5
6
7
8

#显示匹配某个结果之前的3行,使用 -B 选项:
seq 10 | grep "5" -B 3
2
3
4
5

#显示匹配某个结果的前三行和后三行,使用 -C 选项:
seq 10 | grep "5" -C 3
2
3
4
5
6
7
8

#如果匹配结果有多个,会用“--”作为各匹配结果之间的分隔符:
echo -e "a\nb\nc\na\nb\nc" | grep a -A 1
a
b
--
a
b
请我喝杯咖啡吧~