前言
linux 有很多工具能够做文本处理,例如:sort, cut, split, join, paste, comm, uniq, column, rev, tac, tr, nl, pr, head, tail…..,学习 linux 文本处理的懈怠形式(不是最好的办法)可能是:只学习 grep,sed 和 awk。
应用这三个工具,你能够解决近 99% linux 零碎的文本处理问题,而不须要记住下面不同的命令和参数。图片
而且,如果你曾经学会并应用了三者,你就会晓得其中的差别。实际上,这里的差别意味着哪个工具善于解决什么样的问题。
一种更懈怠的形式可能是学习脚本语言(python,perl 或 ruby)并应用它进行每个文本处理。
概述
awk、grep、sed 是 linux 操作文本的三大利器,也是必须把握的 linux 命令之一。
三者的性能都是解决文本,但侧重点各不相同,其中属 awk 性能最弱小,但也最简单。grep 更适宜单纯的查找或匹配文本,sed 更适宜编辑匹配到的文本,awk 更适宜格式化文本,对文本进行较简单格局解决。
简略概括:
grep:数据查找定位
awk:数据切片
sed:数据批改
grep = global regular expression print
用最简略术语来说,grep(全局正则表达式打印)– 命令用于查找文件里符合条件的字符串。从文件的第一行开始,grep 将一行复制到 buffer 中,将其与搜寻字符串进行比拟,如果比拟通过,则将该行打印到屏幕上。grep 将反复这个过程,直到文件搜寻所有行。
留神:这里没有过程执行 grep 存储行、更改行或仅搜寻局部行。
示例数据文件
请将以下数据剪切粘贴到一个名为“sampler.log”的文件中:
boot
book
booze
machine
boots
bungie
bark
aardvark
broken$tuff
robots
一个简略例子
grep 最简略的例子是:
grep
“boo”
sampler.log
在本例中,grep 将遍历文件“sampler.log”的每一行,并打印出其中的每一行 蕴含单词“boo”:
boot
book
booze
boots
然而如果你操作的是大型文件,就会呈现这种状况:如果这些行标识了文件中的哪一行,它们是什么,可能对你更有用,如果须要在编辑器中关上文件,那么能够更容易地跟踪特定字符串做一些扭转。这时候能够通过增加 -n 参数来实现:
grep -n
“boo”
sampler.log
这产生了一个更有用的后果,解释了哪些行与搜寻字符串匹配:
1
:boot
2
:book
3
:booze
5
:boots
另一个乏味的参数是 -v,它会打印出相同的后果。换句话说,grep 将打印所有与搜寻字符串不匹配的行,而不是打印与之匹配的行。
在下列状况下,grep 将打印不蕴含字符串“boo”的每一行,并显示行号,如上一个例子所示
grep -vn
“boo”
sampler.log
4
:machine
6
:bungie
7
:bark
8
:aardvark
9
:broken$tuff
10
:robots
c 选项通知 grep 克制匹配行的打印,只显示匹配行的数量,匹配查问的行。例如,上面将打印数字 4,因为有 4 个在 sampler.log 中呈现“boo”。
grep -c
“boo”
sampler.log
4
l 选项只打印查问中具备与搜寻匹配行的文件的文件名字符串。如果你想在多个文件中搜寻雷同的字符串,这将十分有用。像这样:
grep -l
“boo”
*
对于搜寻非代码文件,一个更有用的选项是 -i,疏忽大小写。这个选项将解决在匹配搜寻字符串时,大小写相等。在上面的例子中,即便搜寻字符串是大写的,蕴含“boo”的行也会被打印进去。
grep -i
“BOO”
sampler.log
boot
book
booze
boots
x 选项只准确匹配。换句话说,以下命令搜寻没有后果,因为没有一行只蕴含 ”boo”
grep -x
“boo”
sampler.log
最初,-A 容许你指定额定的高低文件行,这样就失去了搜寻字符串额定行,例如
grep -A2
“mach”
sampler.log
machine
boots
bungie
正则表达式
正则表达式是形容文本中简单模式的一种紧凑形式。
有了 grep 你能够应用搜寻模式(pattern)。其余工具应用正则表达式 (regexp) 以简单的形式。而 grep 应用的一般字符串,实际上非常简单正则表达式。如果您应用通配符,如 ‘ * ‘ 或 ‘ ? ‘,比方列出文件名等,你能够应用 grep 应用根本的正则表达式进行搜寻
例如搜寻文件以字母 e 结尾的行:
grep
“e$”
sampler.log
booze
machine
bungie
如果须要更宽泛的正则表达式命令,则必须应用 grep-E。
例如,正则表达式命令 ? 将匹配 1 或 0 次呈现 之前的字符:
grep -E
“boots?”
sampler.log
boot
boots
你还能够应用 pipe(|) 联合多个搜寻,它的意思是“或者”,所以你能够这样做:
grep -E
“boot|boots”
sampler.log
boot
boots
特殊字符
如果你想搜寻的是一个特殊字符,该怎么办? 如果你想找到所有的直线,如果蕴含美元字符“$”,则不能执行 grep“$”a_file,因为 ‘$’ 将被解释为正则表达式,相同,你将失去所有的行,其中有任何作为行完结,即所有行。解决方案是“本义”符号,所以您将应用
grep
‘$’
sampler.log
broken$tuff
你还能够应用“-F”选项,它代表“固定字符串”或“疾速”,因为它只搜寻字符串,而不是正则表达式。
更多的 regexp 的例子
参考:http://gnosis.cx/publish/prog…
AWK
由 Aho,Weinberger 和 Kernighan 创立的文本模式扫描和解决语言。
AWK 非常复杂,所以这不是一个残缺的指南,但应该给你一个晓得什么 awk 能够做。它应用起来比较简单,强烈建议应用。
AWK 基础知识
awk 程序对输出文件的每一行进行操作。它能够有一个可选的 BEGIN{} 局部在解决文件的任何内容之前执行的命令,而后主 {} 局部运行在文件的每一行中,最初还有一个可选的 END{}局部操作将在前面执行文件读取实现:
BEGIN {…. initialization awk commands …}
{…. awk commands
for
each line of the file…}
END {…. finalization awk commands …}
对于输出文件的每一行,它会查看是否有任何模式匹配指令,在这种状况下它仅在与该模式匹配的行上运行,否则它在所有行上运行。这些 ‘pattern-matching’ 命令能够蕴含与 grep 一样的正则表达式。
awk 命令能够做一些非常复杂的数学和字符串操作,awk 也反对关联阵列。AWK 将每条线视为由多个字段组成,每个字段由“距离符”分隔。默认状况下,这是一个或多个空格字符,因而行:
this is a line of text
蕴含 6 个字段。在 awk 中,第一个字段称为 $1,第二个字段称为 $2,等等,全副行称为 $0。
字段分隔符由 awk 外部变量 FS 设置,因而如果您设置 FS= “: “ 则它将依据 ‘:’ 的地位划分一行,这对于 /etc/passwd 之类的文件很有用,其余有用的外部变量是 NR,即以后记录号(即行号) NF 是以后行中字段的数量。
AWK 能够对任何文件进行操作,包含 std-in,在这种状况下,它通常与 ‘|’ 命令一起应用,例如,联合 grep 或其余命令。
例如,如果我列出当前目录中的所有文件
ls -l
总用量
140
-rw-r–r–
1
root root
55121
1
月
3
17
:
03
combined_log_format.log
-rw-r–r–
1
root root
80644
1
月
3
17
:
03
combined_log_format_w_resp_time.log
-rw-r–r–
1
root root
71
1
月
3
17
:
55
sampler.log
` 我能够看到文件大小报告为 3 列数据。如果我想晓得它们的总大小,这个目录中的文件我能够做:
ls -l | awk
‘BEGIN {sum=0} {sum=sum+$5} END {print sum}’
135836
请留神,’print sum’ 打印变量 sum 的值,因而如果 sum = 2 则 ‘print sum’ 给出输入 ‘2’ 而 ‘print $ sum’ 将打印 ‘1’,因为第二个字段蕴含值 ‘1’。
因而,会很简略编写一个能够计算平均值的和一列数字的标准偏差的 awk 命令 – 在次要外部积攒 ‘sumx’ 和 ‘sumx2’ 局部,而后应用规范公式计算 END 局部的平均值和标准偏差。
AWK 反对(’for’ 和 ‘while’)循环和分支(应用 ‘if ‘)。所以,如果你想修剪一个文件并且只在每个第 3 行操作,你能够这样做:
ls -l | awk
‘{for (i=1;i<3;i++) {getline}; print NR,$0}’
3
-rw-r–r–
1
root root
80644
1
月
3
17
:
03
combined_log_format_w_resp_time.log
4
-rw-r–r–
1
root root
71
1
月
3
17
:
55
sampler.log
sampler.log
for 循环应用“getline”命令遍历文件,并且每隔 3 次才打印一行。
留神,因为文件的行数是 4,不能被 3 整除,所以最初一个命令提前完成,所以最初的“print $0”命令打印第 4 行,你能够看到咱们也打印了行,应用 NR 变量输入行号。
AWK 模式匹配
AWK 是一种面向行的语言。首先是模式,而后是动作。操作语句用 {and} 括起来。模式可能缺失,或者动作可能缺失,然而,当然不是都。如果短少模式,则对每个输出记录执行操作。一个失落的动作将打印整个记录。
AWK 模式包含正则表达式 (应用与“grep -E”雷同的语法) 和应用的组合特殊符号“&&”示意“逻辑 AND”,“||”示意“逻辑或”,“!”的意思是“逻辑不”。
你也能够做关系模式、模式组、范畴等。
AWK 管制语句
if
(condition) statement [
else
statement ]
while
(condition) statement
do
statement
while
(condition)
for
(expr1; expr2; expr3) statement
for
(var
in
array) statement
break
continue
exit [expression]
AWK 输出 / 输入
留神:printf 命令容许你应用相似 C 的语法更亲密地指定输入格局 例如,你能够指定给定宽度的整数,浮点数或字符串等。
AWK 数学函数
AWK 字符串函数
AWK 命令行和用法
你能够依据须要屡次应用 ‘ -v ‘ 标记将变量传递给 awk 程序,例如
awk -v skip=
3
‘{for (i=1;i<skip;i++) {getline}; print $0}’
sampler.log
booze
bungie
broken$tuff
你还能够应用编辑器编写 awk 程序,而后将其另存为脚本文件,例如:
$ cat awk_strip
#!/usr/bin/awk -f
#only print out every 3rd line of input file
BEGIN {skip=
3
}
{
for
(i=
1
;i<skip;i++)
{getline};
print $0}
而后能够将其用作新的附加命令
chmod u+x awk_strip
./awk_strip sampler.dat
sed = stream editor
sed 对输出流(文件或来自管道的输出)执行根本文本转换单通过流,所以效率很高。然而,sed 可能管道过滤文本,特地区别于其余类型的编辑器。
sed 根底
sed 能够在命令行或 shel l 脚本中应用,以非交互方式编辑文件。兴许最有用的性能是对一个字符串进行“搜寻和替换”到另一个字符串。您能够将 sed 命令嵌入到应用 ‘-e’ 选项调用 sed 的命令行中,或者将它们放在一个独自的文件中 ‘sed.in’ 并应用 ‘-f sed.in’ 选项调用 sed。后一种抉择是如果 sed 命令很简单并波及大量 regexp,则最罕用,例如:
sed-e’s/input/output/’sampler.log
将从 sampler.log 回显到规范输入的每一行,扭转每一行的 ‘input’ 排成 ‘output’。留神 sed 是面向行的,所以如果你想扭转每一行的每一个事件,那么你须要让它成为一个 ‘ 贪心 ’ 的搜寻和替换,如下所示:
sed -e
‘s/input/output/g’
sampler.log
boot
book
booze
machine
boots
bungie
bark
aardvark
broken$tuff
robots
/…/ 中的表达式能够是文字字符串或正则表达式。留神默认状况下,输入将写入 stdout。你能够将其重定向到新文件,或者如果你违心 编辑现有文件,你应该应用 ‘-i’ 标记:
sed -e
‘s/input/output/’
sampler.log > new_file
sed -i -e
‘s/input/output/’
sampler.log
sed 和正则表达式
如果你心愿在搜寻命令中应用的某个字符是特殊符号,例如 ‘/’,该怎么办?(例如在文件名中)或 ‘*’ 等?而后你必须像 grep(和 awk)那样本义符号。跟你说想要编辑 shell 脚本以援用 /usr/local/bin 而不是 /bin,那么你能够这样做
sed -e
‘s//bin//usr/local/bin/’
my_script > new_script
如果你想在搜寻中应用通配符怎么办 – 如何编写输入字符串?你须要应用与找到的模式对应的特殊符号“&”。所以说你想要每行以你的文件中的数字结尾,并用括号括起该数字:
sed -e
‘s/[0-9]*/(&)/’
其中 [0-9] 是所有个位数的 regexp 范畴,而 ‘*’ 是反复计数,示意任何数字的位数。你还能够在 regexp 中应用地位指令,甚至能够将局部匹配后果保留在模式缓冲区,以便在其余中央重用。
其它 SED 命令
个别模式是
sed -e
‘/pattern/ command’
sampler.log
其中 ‘pattern’ 是正则表达式,’command’ 能够是 ‘s’= search&replace,或 ‘p’= print,或 ‘d’= delete,或 ‘i’=insert,或 ‘a’=append 等。请留神,默认操作是打印所有不是无论如何匹配,所以如果你想克制它,你须要应用 ‘-n’ 标记调用 sed,而后你能够应用 ‘p’ 命令来管制打印的内容。所以,如果你想做一个所有的列表 你能够应用的子目录
ls -l | sed -n -e
‘/^d/ p’
因为长列表开始每行都带有 ‘d’ 符号,如果它是一个目录,所以这只会打印进去那些以 ‘d’ 符号结尾的行。同样,如果你想删除所有以评论符号 ‘#’ 结尾的行,你能够应用
sed -e
‘/^#/ d’
sampler.log
也能够应用范畴表单
sed -e
‘1,100 command’
sampler.log
在第 1 -100 行执行“命令”。你也能够用非凡的行号 $ 来示意“完结”文件。因而,如果你想删除文件的前 10 行以外的所有行,您能够应用
sed -e
’11,$ d’
sampler.log
你还能够应用模式范畴表单,其中第一个正则表达式定义范畴的开始,以及第二站。所以,例如,如果你想打印从 ‘boot’ 到 ‘machine’ 的所有行 你能够这样做:
sed -n -e
‘/boot$/,/mach/p’
sampler.log
boot
book
booze
machine
而后只打印出(-n)regexp 给定的给定范畴内的那些行。
延长浏览
应用 sed 能够做的事件还有很多,具体参考:http://www.grymoire.com/Unix/…
总结
Linux 三剑客 awk,sed 和 grep 在性能畛域宽泛用于性能建模、性能监控及性能剖析等方面,也是各大互联网公司测试岗高频面试题,中高端测试人员必备技能之一