textproc.html

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

HTML
3,421
字号
  2&nbsp;# lookup: 对指定数据文件中的每个单词都做一遍字典查询.   3&nbsp;  4&nbsp;file=words.data  # 指定的要搜索的数据文件.   5&nbsp;  6&nbsp;echo  7&nbsp;  8&nbsp;while [ "$word" != end ]  # 数据文件中最后一个单词.   9&nbsp;do 10&nbsp;  read word      # 从数据文件中读, 因为在循环的后边重定向了.  11&nbsp;  look $word &#62; /dev/null  # 不想将字典文件中的行显示出来. 12&nbsp;  lookup=$?      # 'look'命令的退出状态.  13&nbsp; 14&nbsp;  if [ "$lookup" -eq 0 ] 15&nbsp;  then 16&nbsp;    echo "\"$word\" is valid." 17&nbsp;  else 18&nbsp;    echo "\"$word\" is invalid." 19&nbsp;  fi   20&nbsp; 21&nbsp;done &#60;"$file"    # 将stdin重定向到$file, 所以"reads"来自于$file. 22&nbsp; 23&nbsp;echo 24&nbsp; 25&nbsp;exit 0 26&nbsp; 27&nbsp;# ---------------------------------------------------------------- 28&nbsp;# 下边的代码行将不会执行, 因为上边已经有"exit"命令了. 29&nbsp; 30&nbsp; 31&nbsp;# Stephane Chazelas建议使用下边更简洁的方法: 32&nbsp; 33&nbsp;while read word &#38;&#38; [[ $word != end ]] 34&nbsp;do if look "$word" &#62; /dev/null 35&nbsp;   then echo "\"$word\" is valid." 36&nbsp;   else echo "\"$word\" is invalid." 37&nbsp;   fi 38&nbsp;done &#60;"$file" 39&nbsp; 40&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><BCLASS="COMMAND">sed</B>, <BCLASS="COMMAND">awk</B></DT><DD><P>这个两个命令都是独立的脚本语言, 			  尤其适合分析文本文件和命令输出. 			  既可以单独使用, 也可以结合管道和在shell脚本中使用. 	      </P></DD><DT><BCLASS="COMMAND"><AHREF="sedawk.html#SEDREF">sed</A></B></DT><DD><P>非交互式的<SPANCLASS="QUOTE">"流编辑器"</SPAN>, 			  在批处理模式下, 允许使用多个<BCLASS="COMMAND">ex</B>命令. 	      你会发现它在shell脚本中非常有用. </P></DD><DT><BCLASS="COMMAND"><AHREF="awk.html#AWKREF">awk</A></B></DT><DD><P>可编程的文件提取器和文件格式化工具, 			  在结构化的文本文件中, 			  处理或提取特定域(特定列)具有非常好的表现. 			  它的语法与C语言很类似. 	      </P></DD><DT><BCLASS="COMMAND">wc</B></DT><DD><P><EM>wc</EM>可以统计文件或I/O流中的<SPANCLASS="QUOTE">"单词数量"</SPAN>: 	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash $ </SAMP><KBDCLASS="USERINPUT">wc /usr/share/doc/sed-4.1.2/README</KBD><SAMPCLASS="COMPUTEROUTPUT">13  70  447 README</SAMP>[13 lines  70 words  447 characters]</PRE></FONT></TD></TR></TABLE></P><P><KBDCLASS="USERINPUT">wc -w</KBD> 统计单词数量. </P><P><KBDCLASS="USERINPUT">wc -l</KBD> 统计行数量. </P><P><KBDCLASS="USERINPUT">wc -c</KBD> 统计字节数量. </P><P><KBDCLASS="USERINPUT">wc -m</KBD> 统计字符数量. </P><P><KBDCLASS="USERINPUT">wc -L</KBD> 给出文件中最长行的长度. </P><P>使用<BCLASS="COMMAND">wc</B>命令来统计当前工作目录下有多少个<EM>.txt</EM>文件: 	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;$ ls *.txt | wc -l  2&nbsp;# 因为列出的文件名都是以换行符区分的, 所以使用-l来统计.  3&nbsp;  4&nbsp;  5&nbsp;# 另一种方法:  6&nbsp;#      find . -maxdepth 1 -name \*.txt -print0 | grep -cz .  7&nbsp;#      (shopt -s nullglob; set -- *.txt; echo $#)  8&nbsp;  9&nbsp;# 感谢, S.C.</PRE></FONT></TD></TR></TABLE>	    </P><P><BCLASS="COMMAND">wc</B>命令来统计所有以 d - h 开头的文件的大小. 	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">wc [d-h]* | grep total | awk '{print $3}'</KBD><SAMPCLASS="COMPUTEROUTPUT">71832</SAMP>	      </PRE></FONT></TD></TR></TABLE>	    </P><P>使用<BCLASS="COMMAND">wc</B>命令来查看指定文件中包含<SPANCLASS="QUOTE">"Linux"</SPAN>的行一共有多少. 	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">grep Linux abs-book.sgml | wc -l</KBD><SAMPCLASS="COMPUTEROUTPUT">50</SAMP>	      </PRE></FONT></TD></TR></TABLE>	    </P><P>请参考<AHREF="filearchiv.html#EX52">例子 12-35</A>和<AHREF="redircb.html#REDIR4">例子 16-8</A>. </P><P>某些命令的某些选项其实已经包含了<BCLASS="COMMAND">wc</B>命令的部分功能.	      	    <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;... | grep foo | wc -l  2&nbsp;# 这个命令使用的非常频繁, 但事实上它有更简便的写法.  3&nbsp;  4&nbsp;... | grep -c foo  5&nbsp;# 只要使用grep命令的"-c"(或"--count")选项就能达到同样的目的.  6&nbsp;  7&nbsp;# 感谢, S.C.</PRE></FONT></TD></TR></TABLE></P></DD><DT><ANAME="TRREF"></A><BCLASS="COMMAND">tr</B></DT><DD><P>字符转换过滤器. </P><DIVCLASS="CAUTION"><P></P><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/caution.gif"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><AHREF="special-chars.html#UCREF">必须使用引用或中括号</A>, 				这样做才是合理的. 				引用可以阻止shell重新解释出现在<BCLASS="COMMAND">tr</B>命令序列中的特殊字符. 	      中括号应该被引用起来防止被shell扩展. </P></TD></TR></TABLE></DIV><P>无论<KBDCLASS="USERINPUT">tr "A-Z" "*" &#60;filename</KBD>还是<KBDCLASS="USERINPUT">tr A-Z \* 		  &#60;filename</KBD>都可以将<TTCLASS="FILENAME">filename</TT>中的大写字符修改为星号(写到<TTCLASS="FILENAME">stdout</TT>). 	      但是在某些系统上可能就不能正常工作了, 而<KBDCLASS="USERINPUT">tr A-Z	      '[**]'</KBD>在任何系统上都可以正常工作. </P><P><CODECLASS="OPTION">-d</CODE>选项删除指定范围的字符. 	    <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;echo "abcdef"                 # abcdef  2&nbsp;echo "abcdef" | tr -d b-d     # aef  3&nbsp;  4&nbsp;  5&nbsp;tr -d 0-9 &#60;filename  6&nbsp;# 删除"filename"中所有的数字. </PRE></FONT></TD></TR></TABLE></P><P><CODECLASS="OPTION">--squeeze-repeats</CODE> 			(或<CODECLASS="OPTION">-s</CODE>)选项用来在重复字符序列中除去除第一个字符以外的所有字符. 				这个选项在删除多余<AHREF="special-chars.html#WHITESPACEREF">空白</A>的时候非常有用. 	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo "XXXXX" | tr --squeeze-repeats 'X'</KBD><SAMPCLASS="COMPUTEROUTPUT">X</SAMP></PRE></FONT></TD></TR></TABLE></P><P><CODECLASS="OPTION">-c</CODE><SPANCLASS="QUOTE">"complement"</SPAN>选项将会<EM>反转</EM>匹配的字符集. 			通过这个选项, 			<BCLASS="COMMAND">tr</B>将只会对那些<EM>不</EM>匹配的字符起作用. </P><P>	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo "acfdeb123" | tr -c b-d +</KBD><SAMPCLASS="COMPUTEROUTPUT">+c+d+b++++</SAMP></PRE></FONT></TD></TR></TABLE>            </P><P>注意<BCLASS="COMMAND">tr</B>命令支持<AHREF="x13673.html#POSIXREF">POSIX字符类</A>.	  <ANAME="AEN8402"HREF="#FTN.AEN8402"><SPANCLASS="footnote">[1]</SPAN></A>	      </P><P>	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo "abcd2ef1" | tr '[:alpha:]' -</KBD><SAMPCLASS="COMPUTEROUTPUT">----2--1</SAMP>	      </PRE></FONT></TD></TR></TABLE>	    </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX49"></A><P><B>例子 12-18. <BCLASS="COMMAND">转换大写</B>: 把一个文件的内容全部转换为大写. </B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 把一个文件的内容全部转换为大写.   3&nbsp;  4&nbsp;E_BADARGS=65  5&nbsp;  6&nbsp;if [ -z "$1" ]  # 检查命令行参数.  7&nbsp;then  8&nbsp;  echo "Usage: `basename $0` filename"  9&nbsp;  exit $E_BADARGS 10&nbsp;fi   11&nbsp; 12&nbsp;tr a-z A-Z &#60;"$1" 13&nbsp; 14&nbsp;# 与上边的作用相同, 但是使用了POSIX字符集标记方法: 15&nbsp;#        tr '[:lower:]' '[:upper:]' &#60;"$1" 16&nbsp;# 感谢, S.C. 17&nbsp; 18&nbsp;exit 0 19&nbsp; 20&nbsp;#  练习: 21&nbsp;#  重写这个脚本, 通过选项可以控制脚本或者 22&nbsp;#+ 转换为大写或者转换为小写.</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="LOWERCASE"></A><P><B>例子 12-19. <BCLASS="COMMAND">转换小写</B>: 将当前目录下的所有文全部转换为小写. </B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;#  3&nbsp;#  将当前目录下的所有文全部转换为小写.   4&nbsp;#                                        5&nbsp;#  灵感来自于John Dubois的脚本,   6&nbsp;#+ Chet Ramey将其转换为Bash脚本,   7&nbsp;#+ 然后被本书作者精简了一下.   8&nbsp;  9&nbsp; 10&nbsp;for filename in *                # 遍历当前目录下的所有文件.  11&nbsp;do                                                                          12&nbsp;   fname=`basename $filename`                                               13&nbsp;   n=`echo $fname | tr A-Z a-z`  # 将名字修改为小写.  14&nbsp;   if [ "$fname" != "$n" ]       # 只对那些文件名不是小写的文件进行重命名.  15&nbsp;   then 16&nbsp;     mv $fname $n 17&nbsp;   fi   18&nbsp;done    19&nbsp; 20&nbsp;exit $? 21&nbsp; 22&nbsp; 23&nbsp;# 下边的代码将不会被执行, 因为上边的"exit".  24&nbsp;#-------------------------------------------# 25&nbsp;# 删除上边的内容, 来运行下边的内容.  26&nbsp;                                                                 27&nbsp;# 对于那些文件名中包含空白和新行的文件, 上边的脚本就不能工作了.  28&nbsp;# Stephane Chazelas因此建议使用下边的方法:  29&nbsp; 30&nbsp; 31&nbsp;for filename in *    # 不必非得使用basename命令,  32&nbsp;                     # 因为"*"不会返回任何包含"/"的文件.  33&nbsp;do n=`echo "$filename/" | tr '[:upper:]' '[:lower:]'` 34&nbsp;#                             POSIX 字符集标记法. 35&nbsp;#                    添加的斜线是为了在文件名结尾换行不会被 36&nbsp;#                    命令替换删掉.  37&nbsp;   # 变量替换: 38&nbsp;   n=${n%/}          # 从文件名中将上边添加在结尾的斜线删除掉.  39&nbsp;   [[ $filename == $n ]] || mv "$filename" "$n" 40&nbsp;                     # 检查文件名是否已经是小写.  41&nbsp;done 42&nbsp; 43&nbsp;exit $?</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="DU"></A><P><B>例子 12-20. <BCLASS="COMMAND">Du</B>: DOS到UNIX文本文件的转换. </B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# Du.sh: DOS到UNIX文本文件的转换.  3&nbsp;  4&nbsp;E_WRONGARGS=65  5&nbsp;  6&nbsp;if [ -z "$1" ]  7&nbsp;then  8&nbsp;  echo "Usage: `basename $0` filename-to-convert"  9&nbsp;  exit $E_WRONGARGS 10&nbsp;fi 11&nbsp; 12&nbsp;NEWFILENAME=$1.unx 13&nbsp; 14&nbsp;CR='\015'  # 回车. 15&nbsp;           # 015是8进制的ASCII码的回车. 16&nbsp;           # DOS中文本文件的行结束符是CR-LF. 17&nbsp;           # UNIX中文本文件的行结束符只是LF. 18&nbsp; 19&nbsp;tr -d $CR &#60; $1 &#62; $NEWFILENAME 20&nbsp;# 删除回车并且写到新文件中. 

⌨️ 快捷键说明

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