textproc.html

来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 3,421 行 · 第 1/5 页

HTML
3,421
字号
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>文本处理命令</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="外部过滤器, 程序和命令"HREF="external.html"><LINKREL="PREVIOUS"TITLE="时间/日期 命令"HREF="timedate.html"><LINKREL="NEXT"TITLE="文件与归档命令"HREF="filearchiv.html"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="timedate.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">12. 外部过滤器, 程序和命令</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="filearchiv.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="TEXTPROC">12.4. 文本处理命令</A></H1><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="TPCOMMANDLISTING1"></A>处理文本和文本文件的命令</B></P><DL><DT><ANAME="SORTREF"></A><BCLASS="COMMAND">sort</B></DT><DD><P>文件排序, 通常用在管道中当过滤器来使用. 			  这个命令可以依据指定的关键字或指定的字符位置, 			  对文件行进行排序. 使用<CODECLASS="OPTION">-m</CODE>选项, 			  它将会合并预排序的输入文件. 	      想了解这个命令的全部参数请参考这个命令的<EM>info页</EM>. 		  请参考<AHREF="loops1.html#FINDSTRING">例子 10-9</A>, 			  <AHREF="loops1.html#SYMLINKS">例子 10-10</A>, 和<AHREF="contributed-scripts.html#MAKEDICT">例子 A-8</A>.</P></DD><DT><BCLASS="COMMAND">tsort</B></DT><DD><P>拓扑排序, 			  读取以空格分隔的有序对, 			  并且依靠输入模式进行排序. 	      </P></DD><DT><ANAME="UNIQREF"></A><BCLASS="COMMAND">uniq</B></DT><DD><P>这个过滤器将会删除一个已排序文件中的重复行.	      这个命令经常出现在<AHREF="textproc.html#SORTREF">sort</A>命令的管道后边. 	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;cat list-1 list-2 list-3 | sort | uniq &#62; final.list  2&nbsp;# 将3个文件连接起来,  3&nbsp;# 将它们排序,  4&nbsp;# 删除其中重复的行,  5&nbsp;# 最后将结果重定向到一个文件中. </PRE></FONT></TD></TR></TABLE></P><P><CODECLASS="OPTION">-c</CODE>用来统计每行出现的次数, 并把次数作为前缀放到输出行的前面. </P><P>	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">cat testfile</KBD><SAMPCLASS="COMPUTEROUTPUT">This line occurs only once. This line occurs twice. This line occurs twice. This line occurs three times. This line occurs three times. This line occurs three times.</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">uniq -c testfile</KBD><SAMPCLASS="COMPUTEROUTPUT">      1 This line occurs only once.       2 This line occurs twice.       3 This line occurs three times.</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">sort testfile | uniq -c | sort -nr</KBD><SAMPCLASS="COMPUTEROUTPUT">      3 This line occurs three times.       2 This line occurs twice.       1 This line occurs only once.</SAMP>	      </PRE></FONT></TD></TR></TABLE>	     </P><P><KBDCLASS="USERINPUT">sort INPUTFILE | uniq -c | sort -nr</KBD>			 命令先对<TTCLASS="FILENAME">INPUTFILE</TT>文件进行排序, 			 然后统计<EM>每行出现的次数</EM>			 (<BCLASS="COMMAND">sort</B>命令的<CODECLASS="OPTION">-nr</CODE>选项会产生一个数字的反转排序). 			 这种命令模板一般都用来分析log文件或者用来分析字典列表, 	       或者用在那些需要检查文本词汇结构的地方. 	       </P><DIVCLASS="EXAMPLE"><HR><ANAME="WF"></A><P><B>例子 12-11. 分析单词出现的频率</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# wf.sh: 分析文本文件中词汇出现的频率.   3&nbsp;# "wf2.sh"脚本是一个效率更高的版本.   4&nbsp;  5&nbsp;  6&nbsp;# 从命令行中检查输入的文件.   7&nbsp;ARGS=1  8&nbsp;E_BADARGS=65  9&nbsp;E_NOFILE=66 10&nbsp; 11&nbsp;if [ $# -ne "$ARGS" ]  # 检验传递到脚本中参数的个数.  12&nbsp;then 13&nbsp;  echo "Usage: `basename $0` filename" 14&nbsp;  exit $E_BADARGS 15&nbsp;fi 16&nbsp; 17&nbsp;if [ ! -f "$1" ]       # 检查传入的文件是否存在.  18&nbsp;then 19&nbsp;  echo "File \"$1\" does not exist." 20&nbsp;  exit $E_NOFILE 21&nbsp;fi 22&nbsp; 23&nbsp; 24&nbsp; 25&nbsp;######################################################## 26&nbsp;# main () 27&nbsp;sed -e 's/\.//g'  -e 's/\,//g' -e 's/ /\ 28&nbsp;/g' "$1" | tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr 29&nbsp;#                           ========================= 30&nbsp;#                              检查单词出现的频率 31&nbsp; 32&nbsp;#  过滤掉句号和逗号,  33&nbsp;#+ 并且把单词间的空格转化为换行,  34&nbsp;#+ 然后转化为小写,  35&nbsp;#+ 最后统计单词出现的频率并按频率排序.  36&nbsp; 37&nbsp;#  Arun Giridhar建议将上边的代码修改为:  38&nbsp;#  . . . | sort | uniq -c | sort +1 [-f] | sort +0 -nr 39&nbsp;#  这句添加了第2个排序主键, 所以 40&nbsp;#+ 这个与上边等价的例子将按照字母顺序进行排序. 41&nbsp;#  就像他所解释的: 42&nbsp;#  "这是一个有效的根排序, 首先对频率最少的 43&nbsp;#+ 列进行排序 44&nbsp;#+ (单词或者字符串, 忽略大小写) 45&nbsp;#+ 然后对频率最高的列进行排序." 46&nbsp;# 47&nbsp;#  像Frank Wang所解释的那样, 上边的代码等价于:  48&nbsp;#+       . . . | sort | uniq -c | sort +0 -nr 49&nbsp;#+ 用下边这行也行:  50&nbsp;#+       . . . | sort | uniq -c | sort -k1nr -k 51&nbsp;######################################################## 52&nbsp; 53&nbsp;exit 0 54&nbsp; 55&nbsp;# 练习: 56&nbsp;# ----- 57&nbsp;# 1) 使用'sed'命令来过滤其他的标点符号, 58&nbsp;#+   比如分号.  59&nbsp;# 2) 修改这个脚本, 添加能够过滤多个空格或者 60&nbsp;#    空白的能力. </PRE></FONT></TD></TR></TABLE><HR></DIV><P>	       <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">cat testfile</KBD><SAMPCLASS="COMPUTEROUTPUT">This line occurs only once. This line occurs twice. This line occurs twice. This line occurs three times. This line occurs three times. This line occurs three times.</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">./wf.sh testfile</KBD><SAMPCLASS="COMPUTEROUTPUT">      6 this       6 occurs       6 line       3 times       3 three       2 twice       1 only       1 once</SAMP>	       </PRE></FONT></TD></TR></TABLE>	     </P></DD><DT><ANAME="EXPANDREF"></A><BCLASS="COMMAND">expand</B>, <BCLASS="COMMAND">unexpand</B></DT><DD><P><BCLASS="COMMAND">expand</B>命令将会把每个tab转化为一个空格. 			  这个命令经常用在管道中. 	      </P><P><BCLASS="COMMAND">unexpand</B>命令将会把每个空格转化为一个tab. 			  效果与<BCLASS="COMMAND">expand</B>命令相反. </P></DD><DT><ANAME="CUTREF"></A><BCLASS="COMMAND">cut</B></DT><DD><P>一个从文件中提取特定域的工具. 			  这个命令与<AHREF="awk.html#AWKREF">awk</A>中使用的<KBDCLASS="USERINPUT">print 				  $N</KBD>命令很相似, 			 但是更受限. 			 在脚本中使用<BCLASS="COMMAND">cut</B>命令会比使用<BCLASS="COMMAND">awk</B>命令来得容易一些. 			 最重要的选项就是<CODECLASS="OPTION">-d</CODE>(字段定界符)和<CODECLASS="OPTION">-f</CODE>(域分隔符)选项. </P><P>使用<BCLASS="COMMAND">cut</B>来获得所有mount上的文件系统的列表: 	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;cut -d ' ' -f1,2 /etc/mtab</PRE></FONT></TD></TR></TABLE></P><P>使用<BCLASS="COMMAND">cut</B>命令列出OS和内核版本:	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;uname -a | cut -d" " -f1,3,11,12</PRE></FONT></TD></TR></TABLE></P><P>使用<BCLASS="COMMAND">cut</B>命令从e-mail中提取消息头: 	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">grep '^Subject:' read-messages | cut -c10-80</KBD><SAMPCLASS="COMPUTEROUTPUT">Re: Linux suitable for mission-critical apps? MAKE MILLIONS WORKING AT HOME!!! Spam complaint Re: Spam complaint</SAMP></PRE></FONT></TD></TR></TABLE>	    </P><P>使用<BCLASS="COMMAND">cut</B>命令来分析一个文件: 	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;# 列出所有在/etc/passwd中的用户.   2&nbsp;  3&nbsp;FILENAME=/etc/passwd  4&nbsp;  5&nbsp;for user in $(cut -d: -f1 $FILENAME)  6&nbsp;do  7&nbsp;  echo $user  8&nbsp;done  9&nbsp; 10&nbsp;# 感谢Oleg Philon对此的建议. </PRE></FONT></TD></TR></TABLE></P><P><KBDCLASS="USERINPUT">cut -d ' ' -f2,3 filename</KBD>等价于<KBDCLASS="USERINPUT">awk -F'[ ]' '{ print $2, $3 }' filename</KBD></P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>你甚至可以指定换行符作为字段定界符. 这个小伎俩实际上就是在命令行上插入一个换行(<BCLASS="KEYCAP">RETURN</B>). (译者: linux使用lf作为换行符). </P><P>	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">cut -d' ' -f3,7,19 testfile</KBD><SAMPCLASS="COMPUTEROUTPUT">This is line 3 of testfile. This is line 7 of testfile. This is line 19 of testfile.</SAMP>	      </PRE></FONT></TD></TR></TABLE>	  </P><P>感谢, Jaka Kranjc指出这点. </P></TD></TR></TABLE></DIV><P>请参考<AHREF="mathc.html#BASE">例子 12-43</A>.</P></DD><DT><BCLASS="COMMAND">paste</B></DT><DD><P>将多个文件, 以每个文件一列的形式合并到一个文件中, 			  合并后文件中的每一列就是原来的一个文件. 	      与<BCLASS="COMMAND">cut</B>结合使用, 经常用于创建系统log文件. 	    </P></DD><DT><BCLASS="COMMAND">join</B></DT><DD><P>这个命令与<BCLASS="COMMAND">paste</B>命令属于同类命令. 			  但是它能够完成某些特殊的目地. 			  这个强力工具能够以一种特殊的形式来合并两个文件, 			  这种特殊的形式本质上就是一个关联数据库的简单版本. 	      </P><P><BCLASS="COMMAND">join</B>命令只能够操作两个文件. 	      它可以将那些具有特定标记域(通常是一个数字标签)的行合并起来,	      并且将结果输出到<TTCLASS="FILENAME"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?