<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[静怡家园]]></title> 
<link>http://www.zhanghaijun.com/index.php</link> 
<description><![CDATA[书山有路勤为径，学海无涯苦作舟！]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[静怡家园]]></copyright>
<item>
<link>http://www.zhanghaijun.com/post//</link>
<title><![CDATA[Linux下文本的高效处理]]></title> 
<author>碟舞飞扬 &lt;webmaster@zhanghaijun.com&gt;</author>
<category><![CDATA[Linux技术]]></category>
<pubDate>Tue, 27 Aug 2013 15:41:10 +0000</pubDate> 
<guid>http://www.zhanghaijun.com/post//</guid> 
<description>
<![CDATA[ 
	1 引言 <br/>所谓的文本处理是指对文本进行查找、替换、删除、排序等操作, linux在文本处理方面提供了大量优秀的工具, 使得在linux下进行文本处理极其的方便. <br/><br/>我们平常的工作中, 经常会用到文本处理, 比如日志分析, 比如文本抽取, 等等, 所以掌握好文本处理, 将会对我们的工作起到极大的作用. <br/><br/>下面我就来逐个介绍下这些强大的工具, 对于我觉得大家可能比较熟知的工具及用法, 我会略过, 或者粗讲下. <br/><br/>2 关于输入 <br/>Linux哲学中, 为了更好的组合各种命令达到更加强大的功能, 大多数文本处理命令的输入既可以是文件, 也可以是标准输入, 如果没有指定输入文件, 则默认从标准输入读数据. 输出都是标准输出, 方面传给管道线的下一个命令, 想要输出到文件的话, 重定向下即可. 下面介绍的这些命令, 如无特殊说明, 则都可以从文件或者标准输入读入数据. <br/><br/>3 文本输出 <br/>3.1 整个输出 <br/>echo <br/><br/>输入为命令行参数<br/>非常常用的命令, 主要用作输出字符串. 如果只是为了向管道线的下一个命令传输入的话, 可以使用Here String: <br/><br/>echo xxx &#124; md5sum<br/>md5sum <<< xxx<br/>后者速度上应该会快一点, 不需要经过管道. <br/><br/>-n <br/><br/>不输出换行符(默认输出换行符) <br/>-e <br/><br/>解释转义符, 常用的转义符 &#92;t, &#92;n; 这个命令还有个最常用的用途就是输出ANSI颜色:<br/><br/>echo -e '&#92;033[1;31mHello, &#92;033[0m&#92;033[1;33mworld!&#92;033[0m'<br/>Hello, world!<br/><br/>这个工具可以更方便的输出ANSI颜色. <br/><br/>-E <br/><br/>不解释转义符<br/><br/>printf <br/><br/>输入为命令行参数<br/>更强大的输出你想要的文本的命令, 类似C里面的printf <br/><br/>printf '&#92;033[1;31m%s, &#92;033[0m&#92;033[1;33m%d&#92;033[0m and &#92;u4e2d&#92;u6587!&#92;n' "Hello" 34<br/>Hello, 34 and 中文!<br/><br/>不过此命令较echo来说, 使用率会低很多, 大多数情况下echo就能搞定了. <br/><br/>yes [STRING] <br/><br/>输入为命令行参数<br/>不停的输出字符串STRING, 默认是y. 这个命令用处比较少, 但会有用, 比如测试tail命令. <br/><br/>cat (concatenate) <br/><br/>此命令最大的用途应该就是显示特殊字符了, 如果你告诉我你经常用它给管道线的下一个命令传输入的话, 那么就太浪费了:<br/><br/>cat file &#124; grep xxx<br/>grep xxx file<br/>前者相比后者多启动了一个进程, 还经过了管道. file很大的话, 性能差距很容易就看出来了. <br/><br/>-E <br/><br/>在行尾显示$, 有时候行尾是空格或者TAB, 看不清行尾是哪里, 加了这个选项就知道了 <br/>-T <br/><br/>输出的时候用^I代替TAB符号, 这样很容易知道那一坨空白到底谁是TAB了 <br/>-v <br/><br/>用^和M-表示法输出不可打印字符<br/><br/>taoshanwen@taoshanwen-laptop ~$ echo -e '&#92;r' &#124; cat -v<br/>^M<br/>-e <br/><br/>相当于-vE <br/>-t <br/><br/>相当于-vT <br/>-A <br/><br/>相当于-vET, 一般这个选项用的最多<br/><br/>-n <br/><br/>显示行号, 应该有同学感兴趣 <br/>-b <br/><br/>只对非空行显示行号, 有人感兴趣吗?<br/><br/>-s <br/><br/>对连续的空行只输出一个空行, 见过好多同学有这样的需求<br/><br/>tac <br/><br/>看名字知道了, 它和cat是反的, 倒着输出, 先输出最后一行, 接着是倒数第二行, 最后输出的是第一行<br/><br/>-s, –separator=STRING <br/><br/>设定分隔符, 代替&#92;n分割文本<br/><br/>rev (reverse) <br/><br/>这个命令和cat也是反的, 不过它不像tac那样, 它输出行的顺序和cat也是一样的, 不过输出每行的时候, 先输出最后一个字符, 接着是倒数第二个字符, 最后才是第一个字符, 下面这个命令可以把输入全部倒过来:<br/><br/>tac &#124; rev<br/>nl (number lines) <br/><br/>更强大的行号显示工具, 可以控制行号的格式, 宽度. 没有特殊的需求, 用cat -n就够了.<br/><br/>3.2 部分输出 <br/>head <br/><br/>只显示文本的开头几行, 比如head -2只显示前面2行 <br/>tail <br/><br/>这个命令相对head来说, 最常用的用途就是不停的打印文件的最新内容了(tail -f)<br/><br/>-n, -K, –lines=K <br/><br/>显示尾部K行, -n +K显示第K行到文本尾部的所有内容 <br/>-f, –follow[=&#123;name&#124;descriptor&#125;] <br/><br/>这个选项表示如果文件尾部有新数据追加进来, 也会显示出来. 这个选项可以根据文件名(name)和文件描述符(descriptor)来监视文件是否有更新. 默认是descriptor. <br/>–retry <br/><br/>当文件不可访问时, 进行重试, 这个选项和–follow=name组合起来比较有用 <br/>-F <br/><br/>相当于–follow=name –retry<br/><br/>4 文本搜索 <br/>4.1 grep (Global Regular Expression Print) <br/>非常常用的命令, 打印文本中匹配模式的行, 下面的选项最好都能掌握. <br/><br/>grep [OPTIONS] PATTERN [FILE...]<br/>grep [OPTIONS] [-e PATTERN &#124; -f FILE] [FILE...]<br/>-E, –extended-regexp <br/><br/>使用扩展正则表达式(ERE), 默认的是基础正则表达式(BRE), BRE中元字符?, +, &#123;, &#124;, (, )失去特殊意义(你是否遇到grep "a&#124;b"是否不能打印出含有a或者b的行?), 想要表达特殊意义的话, 需要用转义字符进行转义(&#92;), &#92;?, &#92;+等 <br/>-F, –fixed-strings <br/><br/>把pattern当作一个固定的字符串, 不进行正则解析. 当你要搜索非正则的固定字符串时(还可能含有正则元字符), 这个选项会非常有用, 而且由于不需要解析正则, 速度会快些. <br/>-P, –perl-regexp <br/><br/>把pattern解析为perl的正则(PCRE), 由于perl的正则强大而简洁, 所以可以多尝试着使用这个选项.<br/><br/>-i, –ignore-case <br/><br/>搜索pattern的时候, 忽略大小写. 如果没有这个选项, 可以使用PCRE, 比如:<br/><br/>grep -P "(?i)AB"<br/>-v, –invert-match <br/><br/>显示不能匹配pattern的行 <br/>-e pattern <br/><br/>如果你想要指定多个搜索pattern, 或者你想要搜索的pattern由减号(-)开头(如果直接grep pattern的话, 会被解析为grep的选项), 就可以用这个选项了. <br/><br/>-f FILE, –file=FILE <br/><br/>从文件中获取pattern, 每行一个pattern<br/><br/>-x, –line-regexp <br/><br/>pattern必须要匹配整行, 这个选项等价于 "^pattern$" <br/>-w, –word-regexp <br/><br/>pattern必须要匹配整个单词, 这个选项等价于 "&#92;bpattern&#92;b"<br/><br/>-c, –count <br/><br/>不打印匹配的行, 只打印匹配的行数, 等价于grep pattern &#124; wc -l <br/>–color[=WHEN], –colour[=WHEN] <br/><br/>用颜色高亮出匹配的:<br/><br/>(require 'coding-settings)<br/>&nbsp;&nbsp; ("C-x U"&nbsp;&nbsp; revert-buffer-with-coding-system-no-confirm-sb)))<br/>&nbsp;&nbsp; ("C-x M-C" set-buffer-file-coding-system)))<br/>&nbsp;&nbsp;(set-buffer-file-coding-system 'unix))<br/>&nbsp;&nbsp;(set-buffer-file-coding-system 'dos))<br/>-m NUM, –max-count=NUM <br/><br/>当发现NUM个匹配行后, 停止扫描剩下的文本. <br/>-q, –quiet, –silent <br/><br/>不打印任何信息, 发现匹配即退出, 并返回0, 否则返回1. 我们经常只是想查看整个文本里面是否有匹配, 这时候这个选项就非常有用了, 速度会快很多. <br/>-o, –only-matching <br/><br/>只显示匹配pattern的字符串, 匹配行的其余部分不显示 <br/>-n, –line-number <br/><br/>在匹配行前面打印行号<br/><br/>有时候想看看匹配行周围都是啥, 下面这几个选项就非常有用了: <br/><br/>-A NUM, –after-context=NUM <br/><br/>打印匹配行的后面NUM行 <br/>-B NUM, –before-context=NUM <br/><br/>打印匹配行的前面NUM行 <br/>-C NUM, -NUM, –context=NUM <br/><br/>打印匹配行的周围NUM行<br/><br/>-a, –text <br/><br/>有时候文件中含有一些非可打印字符, grep可能会把它识别成二进制文件, 这时候grep只会打印出是否匹配pattern的信息, 并不会打印匹配的每行, 这个选项会强制grep把该文件当文本文件处理<br/><br/>-R, -r, –recursive <br/><br/>递归处理文件夹下的所有文件<br/><br/>-l, –files-with-matches <br/><br/>不打印匹配的行, 只打印匹配的文件 <br/>-L, –files-without-match <br/><br/>和-l相反, 不打印匹配的行, 只打印不匹配的文件 <br/>-h, –no-filename <br/><br/>搜索多个文件时, 会在每行前面输出文件名, 如果你不喜欢, 使用此选项吧.<br/><br/>4.2 fgrep <br/>grep -F <br/><br/>4.3 egrep <br/>grep -E <br/><br/>4.4 rgrep <br/>grep -r <br/><br/>4.5 agrep (approximate grep) <br/>grep的模糊匹配版本 <br/><br/>4.6 zgrep <br/>对压缩文件进行grep, 接受的选项和grep完全一样 <br/><br/>4.7 sgrep (structured grep) <br/>对结构化的文本, 如SGML、XML、HTML进行搜索、抽取, 功能非常强大 <br/><br/>4.8 nrgrep (Nondeterministic Reverse grep) <br/>类似agrep <br/><br/>5 文本摘要 <br/>5.1 wc (word count) <br/>最主要的用途就是统计行数 <br/><br/>-l, –lines <br/><br/>最常用的选项, 统计行数 <br/>-L, –max-line-length <br/><br/>输出文本最长行的长度 <br/>-w, –words <br/><br/>输出单词数 <br/>-m, –chars <br/><br/>输出字符数 <br/>-c, –bytes <br/><br/>输出字节数<br/><br/>5.2 md5sum <br/>打印文本的md5, 主要用作文件校验, 防止文件传输时发生错误或者被篡改. -c选项检查md5是否正确 <br/><br/>6 排序去重 <br/>6.1 sort <br/>非常常用的命令, 啥序都能排 <br/><br/>-r, –reverse <br/><br/>逆序排序, 默认是按从小到大排, -r后就从大到小了<br/><br/>-c, –check, –check=diagnose-first <br/><br/>检查输入文件是否是有序的, 不是的话, 会打印哪行开始不是有序的 <br/>-C, –check=quiet, –check=silent <br/><br/>类似-c, 但是不打印错误信息, 只返回错误码1<br/><br/>-k, –key=POS1[,POS2] <br/><br/>这个应该是sort最nb的地方了, 可以精确控制要排序的对象. POS具备这样的形式:<br/><br/>F[.C][OPTS]<br/>其中, F是字段号, C是字符号, OPTS是排序选项, 可以每个字段排序的规则不一样. F, C都是从1开始 <br/><br/>sort -t ' ' -k1,1d -k2.2,2n <<-EOF<br/>bb 113<br/>aa 224<br/>cc 323<br/>dd 444<br/>cc 513<br/>EOF<br/><br/>aa 224<br/>bb 113<br/>cc 513<br/>cc 323<br/>dd 444<br/>-u, –unique <br/><br/>对输出结果进行去重, 只输出重复的记录中的第一条记录 <br/>-m, –merge <br/><br/>对有序的输入文件进行归并, 这个选项使得你能够在多核机器上优化大数据集的排序 <br/>-s, –stable <br/><br/>使得sort成为稳定排序 <br/>-T, –temporary-directory=DIR <br/><br/>设定指定的临时文件夹, 存放中间数据. 当你排序非常大的文件时, 而且/tmp所在的分区空间不够时, 就会用到该选项了<br/><br/>-n, –numeric-sort <br/><br/>把输入当整数来排序, 可以有负数, 但是不能含有加号(+)的正数, 这种输入用-g搞定吧 <br/>-g, –general-numeric-sort <br/><br/>把输入当作数值来排序, 可以有浮点数. 如果输入是整数的话, 就用-n搞定吧, 人家性能高些. <br/>-h, –human-numeric-sort <br/><br/>可以排序2K, 1G等带单位的数字, 很爽啊, 想排序某文件夹下所有文件和文件的大小吗:<br/><br/>du -sh * &#124; sort -h<br/>-M, –month-sort <br/><br/>按月份进行排序, `JAN' < `FEB' < … < `DEC' <br/>-d, –dictionary-order <br/><br/>按字典序排序, 忽略字母、数字、空白字符外的所有字符 <br/>-V, –version-sort <br/><br/>你开发的软件有很多版了没? 排下吧, 根据版本号<br/><br/>-t, –field-separator=SEP <br/><br/>设置字段分隔符, 默认为空白字符. 可惜的是, 这个字段分隔符只能为单个字符 <br/>-b, –ignore-leading-blanks <br/><br/>忽略前导空白字符 <br/>-f, –ignore-case <br/><br/>忽略大小写 <br/>-i, –ignore-nonprinting <br/><br/>忽略不可打印字符<br/><br/>-R, –random-sort <br/><br/>随机排序, 我想你会用到它的, 反正我用过几次. 不过排序结果不完全随机, 因为sort会先对每行进行hash, 然后对hash值进行排序, 所以相同的行一定会排到一块. 不过也许, 这正是你想要的. 如果你想更乱或者更加强大的功能的话, 看这里<br/><br/>陷阱 <br/><br/>你是否经常sort一个中文文件却得不到正确结果? 那就对了, 你肯定没设置好语言环境(locale), 试试LC_ALL=C sort吧. sort会根据本地语言环境对输入文本进行排序. LC_ALL=C表示会根据字节值来排序. 或许你说我怎么见到的都是LANG=C sort啊, 来, 我们看看bash info上关于LANG和LC_ALL的解释:<br/><br/>LANG&nbsp;&nbsp; Used to determine the locale category for any category not specifically selected with a variable starting with LC_.<br/>LC_ALL This variable overrides the value of LANG and any other LC_ variable specifying a locale category.<br/>LC_COLLATE<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This variable determines the collation order used when sorting the results of pathname expansion, and&nbsp;&nbsp;determines&nbsp;&nbsp;the<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; behavior&nbsp;&nbsp;of&nbsp;&nbsp;range&nbsp;&nbsp;expressions,&nbsp;&nbsp;equivalence&nbsp;&nbsp;classes, and collating sequences within pathname expansion and pattern<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matching.<br/>LANG <br/><br/>如果你没有用LC_来设定某个分类的locale, 将会使用LANG来决定这个分类的locale <br/>LC_ALL <br/><br/>该变量会覆盖LANG和LC_ <br/>LC_COLLATE<br/>该变量设置排序时的locale<br/><br/>所以, sort时, 设置LC_ALL是最保险的做法. <br/><br/>6.2 tsort (topological sort) <br/>拓朴排序, 该命令可能会用的比较少 <br/><br/>tsort <<EOF<br/>a b c<br/>d<br/>e f<br/>b c d e<br/>EOF<br/>输出: <br/><br/>a<br/>b<br/>c<br/>d<br/>e<br/>f<br/>6.3 uniq <br/>也是非常常用的一个命令. 这个命令主要用来对有序序列进行去重, 所以它常和sort联合起来使用, 但是sort -u本身就有去重的功能, 所以当你仅仅只是为了去重时, sort -u就可以帮你搞定了(当输入文本巨大时, 可以用hash来去重提高性能, 比如awk的关联数组), 所以呢, 当年需要对重复的数据进行统计时, 会用到uniq. 当然其实uniq相比sort -u而言, 对重复数据有更加强大的处理 <br/><br/>-c, –count <br/><br/>在每行文本前面输出重复次数 <br/>-d, –repeated <br/><br/>只显示重复的行, 重复的行只显示一行 <br/>-D, –all-repeated[=delimit-method] <br/><br/>显示所有重复的行, 注意该选项与选项-d的区别 <br/>-u, –unique <br/><br/>只打印不重复的行 <br/>-i, –ignore-case <br/><br/>比较的时候不区分大小写 <br/>-f, –skip-fields=N <br/><br/>不比较前面N个字段, 字段分隔符为空白字符 <br/>-s, –skip-chars=N <br/><br/>不比较前面N个字符 <br/>-w, –check-chars=N <br/><br/>每行最多比较前面N个字符<br/><br/>实例演示 <br/><br/>大家看了uniq上面几个选项后, 是不是有uniq没有太大用处的感觉? 这都是错觉, 下面我给大家演示下uniq在集合运算(统计中有大量的应用)方面巧妙的应用.<br/><br/>并集 <br/><br/>sort A B &#124; uniq<br/>交集 <br/><br/>sort A B &#124; uniq -d <br/>差集(A-B) <br/><br/>sort A B B &#124; uniq -u<br/><br/>缺陷 <br/><br/>不能控制字段分隔符 <br/>不能像sort -k那样精确的控制要比较的对象 <br/>6.4 comm <br/>逐行比较两个有序文件, 分三列输出文件1独有的行、文件2独有的行、文件12共有的行, <br/><br/>$ cat ab<br/>ax<br/>by<br/>cz<br/><br/>$ cat ac<br/>ax<br/>bd<br/>cz<br/><br/>$ comm ab ac<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ax<br/>&nbsp;&nbsp;&nbsp;&nbsp;bd<br/>by<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cz<br/>-1 <br/><br/>不输出第一列(文件1独有的行) <br/>-2 <br/><br/>不输出第二列(文件2独有的行) <br/>-3 <br/><br/>不输出第三列文件3独有的行 <br/>–check-order <br/><br/>检查输入文件是否有序 <br/>–nocheck-order <br/><br/>不检查输入文件是否有序 <br/>–output-delimiter=STR <br/><br/>设定输出分隔符, 默认为TAB <br/>实例演示 <br/><br/>交集 <br/><br/>comm -12 <(sort A) <(sort B) <br/>差集(A-B) <br/><br/>comm -23 <(sort A) <(sort B)<br/><br/>6.5 shuf (shuffle) <br/>如果sort -R产生的结果还不够乱的话, 我想这个命令应该就是你需要的了. 该命令产生完全乱序的结果, 而且速度应该比sort -R快(shuf不用排序), 还有功能更强大 <br/><br/>-e, –echo <br/><br/>对命令行参数乱序 <br/>-i, –input-range=LO-HI <br/><br/>对LO到HI之间的数字进行乱序, 比如shuf -i 12-100<br/><br/>7 操作字段 <br/>7.1 cut <br/>挺常用的一个命令, 能非常方便的取某个字段 <br/><br/>-f, –fields=LIST <br/><br/>选择要输出的字段 <br/>-c, –characters=LIST <br/><br/>选择要输出的字符 <br/>-b, –bytes=LIST <br/><br/>选择要输出的字节 <br/>-d, –delimiter=DELIM <br/><br/>设定字段分隔符, 默认是TAB. 可惜的是, 该分隔符也只能是单个字符. <br/>–complement <br/><br/>取设定的选择LIST的补集 <br/>-s, –only-delimited <br/><br/>忽略不包含分隔符的行, 默认操作是输出整行 <br/>–output-delimiter=STRING <br/><br/>设定输出分隔符 <br/>LIST <br/><br/>-f, -c, -b选项使用的列表, 可以有下面几种形式:<br/><br/>N <br/><br/>第N个字段/字节/字符 <br/>N- <br/><br/>从第N个到最后一个 <br/>M-N <br/><br/>从第M个到第N个 <br/>-M <br/><br/>从第一个到第N个 <br/>列表可以有多个, 之间以逗号分割, 比如: <br/><br/>cut -f1-3,4-7<br/>7.2 paste <br/>这个命令很有意思, 把两个文件按行粘贴到一块, 曾经我想自己写个程序搞定这个需求, 后来发现linux下竟然已经有这玩意了(linux总能给你带来惊喜) <br/><br/>$ cat num2<br/>1<br/>2<br/>$ cat let3<br/>a<br/>b<br/>c<br/>$ paste num2 let3<br/>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a<br/>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c<br/>-d, –delimiters=LIST <br/><br/>paste两个文件的时候, 默认是用TAB分割, 这个选项设定分隔符, 同为可惜的是, 只能为单个字符(主要是paste可以粘贴多个文件, 这个选项的第二个字符用来分割第二个和第三个文件)<br/><br/>-s, –serial <br/><br/>默认paste是竖着粘贴的, 加了这个选项后, 就横着粘贴了:<br/><br/>$ paste -s num2 let3<br/>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br/>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c<br/>7.3 join <br/>这是一个稍微高级点的命令, 它把输入文件当成一个key/value对, 然后会把同一个key的所有value粘贴到一块, 来个例子: <br/><br/>$ cat file1<br/>a 1<br/>b 2<br/>c 3<br/>$ cat file2<br/>a 4<br/>c 6<br/>$ join file1 file2<br/>a 1 4<br/>c 3 6<br/>join默认把第一额字段当作key, 字段之间以空格分割, 作为key的字段必须有序. <br/><br/>-i, –ignore-case <br/><br/>比较字段时, 忽略大小写 <br/>-t CHAR <br/><br/>使用CHAR作为字段分隔符, 又是只能为单个字符(杯具…)<br/><br/>-1 FIELD <br/><br/>设定第一个文件的key为第FIELD个字段 <br/>-2 FIELD <br/><br/>设定第二个文件的key为第FIELD个字段 <br/>-j FIELD <br/><br/>-1 FIELD -2 FIELD<br/><br/>-a FILENUM <br/><br/>join默认只打印拥有相同key的行, 该选项会打印第FILENUM个文件中没有匹配上的行 <br/>-v FILENUM <br/><br/>和-a选项有点类似, 该选项只打印第FILENUM个文件中没有匹配上的行, 不会打印匹配上的行<br/><br/>–check-order <br/><br/>检查输入文件作为key的字段是否有序 <br/>–nocheck-order <br/><br/>不检查输入文件作为key的字段是否有序<br/><br/>-o FIELD-LIST <br/><br/>高级的控制输出对象的选项, FIELD-LIST中的每个元素具有下面这样的形式:<br/><br/>0 <br/><br/>表示做为key的字段 <br/>M.N <br/><br/>M为文件号, 取值为0或者1, N为字段号, M.N就是取第M个文件第N个字段 <br/>每个元素之间以逗号或者空格分割 <br/><br/>-e EMPTY <br/><br/>-o选项中, 可能文件M中没有字段号N, 这时候输出的时候用EMPTY代替.<br/><br/>8 操作字符 <br/>8.1 tr (translate) <br/>主要对文本中的字符进行替换、删除. <br/><br/>该命令只支持标准输入, 不支持从文件输入. <br/>tr仅支持单字节字符. <br/>tr [OPTION]... SET1 [SET2]<br/>字符集合可以由一系列的字符构成, 也可以具有以下形式: <br/><br/>CHAR1-CHAR2 <br/><br/>从CHAR1到CHAR2的所有字符 <br/>[CHAR*] <br/><br/>这种形式只能出现在SET2中, 表示拷贝CHAR直到SET2和SET1的长度相等 <br/>[CHAR*REPEAT] <br/><br/>REPEAT个CHAR <br/>[:alnum:] <br/><br/>所有的字母和数字 <br/>[:alpha:] <br/><br/>所有的字母 <br/>[=CHAR=] <br/><br/>和CHAR属于同一个字符类中的所有字符<br/><br/>当提供2个字符集合时, 表示把SET1中的字符替换成SET2中的对应的字符, 比如: <br/><br/>tr a A < file # 把文件file中的小写a都变成大写A<br/>tr '[:lower:]' '[:upper:]' < file # 把文件file全部大写<br/>-d, –delete <br/><br/>删除出现在集合1中的所有字符. 下面的命令把文件file中所有的行连成一行:<br/><br/>tr -d "&#92;r&#92;n" < file<br/>-s, –squeeze-repeats <br/><br/>把SET1中连续的字符都替换成1个字符, 当SET2也提供时, 首先执行删除连续字符操作, 然后才执行替换操作<br/><br/>-c, -C, –complement <br/><br/>使用SET1的补集<br/><br/>-t, –truncate-set1 <br/><br/>首先把SET1中的字符截断到和SET2长度相等<br/><br/>陷阱 <br/><br/>经常见到有同学对会含有中文的文件用上面的方法进行大小写转换:<br/><br/># 终端编码为GB18030编码<br/>$ tr '[:upper:]' '[:lower:]' <<< 琄<br/>琸<br/>为什么琄会变成琸呢? <br/><br/>上面我们说到, tr是按字节来处理的, 而GB18030编码第二个字节编码范围为0×40-0×7E和0×80-0×FE, 这样, 第二个字节就可能出现ASCII码, 我们来看下上面2个汉字的GB18030编码值: <br/><br/>$ od -c&nbsp;&nbsp;<<< 琄<br/>0000000 254&nbsp;&nbsp; K&nbsp;&nbsp;&#92;n<br/>0000003<br/>$ od -t x1&nbsp;&nbsp;<<< 琄<br/>0000000 ac 4b 0a<br/>0000003<br/><br/>$ od -c&nbsp;&nbsp;<<< 琸<br/>0000000 254&nbsp;&nbsp; k&nbsp;&nbsp;&#92;n<br/>0000003<br/>$ od -t x1&nbsp;&nbsp;<<< 琸<br/>0000000 ac 6b 0a<br/>0000003<br/>看来确实如此, 琄的第二个字节是字符大K, 琸的第二个字节是字符小k. <br/><br/>看来, 如果文本里含有多字节字符, 使用tr的时候得小心咯. <br/><br/>8.2 expand <br/>每个编辑器对TAB的显示设置不一样, 有的显示为8个字符, 有的显示为4个字符, 这样就造成了在A编辑器下排版很漂亮, 到了B编辑器下变得一团糟, 所以编码的时候最好使用空白字符代替TAB(Emacs中这样设置: (setq-default indent-tabs-mode nil),&nbsp;&nbsp;), expand命令也可以帮你把TAB转换成空格 <br/><br/>-i, –initial <br/><br/>不转换非空白字符后的TAB <br/>-t, –tabs=NUMBER <br/><br/>设置一个TAB转换成几个空格, 默认是8<br/><br/>8.3 unexpand <br/>Makefile缩进的时候, 必须是TAB, 所以有时候又需要把空格变成TAB, 就靠unexpand了 <br/><br/>-a, –all <br/><br/>转换所有的空格, 默认情况下只转换开头的空格 <br/>–first-only <br/><br/>只转换开头的空格 <br/>-t, –tabs=N <br/><br/>几个空格转换成一个TAB, 默认是8<br/><br/>8.4 colrm (COLumn ReMove) <br/>colrm [start [stop]]<br/>该命令只支持标准输入, 不支持从文件输入. <br/><br/>删除每行从start到stop之间的字符, 如果stop没有指定的话, 则删除到末尾. 需要注意的是, TAB被认为占8列(不知道为啥这样搞) <br/><br/>9 文本切割 <br/>9.1 split <br/>切割文本INPUT成文件PREFIXaa, PREFIXab … 默认每个文件1000行, PREFIX为x <br/><br/>split [OPTION]... [INPUT [PREFIX]]<br/>-l, –lines=NUMBER <br/><br/>按行切割, 每个输出文件NUMBER行, 比较常用的切割方式 <br/>-b, –bytes=SIZE <br/><br/>按字节切分 <br/>-C, –line-bytes=SIZE <br/><br/>每个文件最多SIZE个自己, 但是每行都完整的保存到一个输出文件中, 即不像-b那样, 可能一个整行被拆分到多个文件中去 <br/>-d, –numeric-suffixes <br/><br/>使用数字做为后缀名<br/><br/>9.2 csplit (context split) <br/>根据模式切割文件, 简单了解即可 <br/><br/>csplit [OPTION]... FILE PATTERN...<br/>10 文本编码 <br/>10.1 iconv <br/>经常会用到, 主要用来转换编码 <br/><br/>–list, -l <br/><br/>列出可以识别的编码 <br/>-c <br/><br/>转换的时候, 忽视无效的字符, 如果没有加这个选项, iconv碰到这个无效字符会直接报错退出, 所以最好加上这个选项<br/><br/>10.2 enca <br/>我们经常需要知道文件的编码, 这个命令帮你搞定 <br/><br/>11 文本格式化 <br/>打扮一下你的文本吧. <br/><br/>11.1 column <br/>按列漂亮的输出: <br/><br/>$ (printf "PERM LINKS OWNER GROUP SIZE DAY HH:MM NAME&#92;n"; ls -l &#124; sed 1d) &#124; column -t<br/>PERM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LINKS&nbsp;&nbsp;OWNER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GROUP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SIZE&nbsp;&nbsp; DAY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HH:MM&nbsp;&nbsp;NAME<br/>drwxr-xr-x&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-03&nbsp;&nbsp;22:54&nbsp;&nbsp;ai<br/>drwxr-xr-x&nbsp;&nbsp;26&nbsp;&nbsp;&nbsp;&nbsp; taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;11:59&nbsp;&nbsp;algorithm<br/>drwxr-xr-x&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-09&nbsp;&nbsp;13:35&nbsp;&nbsp;arch<br/>drwxr-xr-x&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-03&nbsp;&nbsp;22:47&nbsp;&nbsp;c-c++<br/>drwxr-xr-x&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-14&nbsp;&nbsp;20:33&nbsp;&nbsp;CIP<br/>drwxr-xr-x&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-03&nbsp;&nbsp;22:47&nbsp;&nbsp;computer-chess<br/>drwxr-xr-x&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;00:23&nbsp;&nbsp;computer-go<br/>drwxr-xr-x&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-10&nbsp;&nbsp;16:25&nbsp;&nbsp;database<br/>drwxr-xr-x&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;00:57&nbsp;&nbsp;distributed<br/>drwxr-xr-x&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-03&nbsp;&nbsp;22:47&nbsp;&nbsp;genetic-prog<br/>drwxr-xr-x&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-03&nbsp;&nbsp;22:47&nbsp;&nbsp;infosec<br/>drwxr-xr-x&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2011-03-19&nbsp;&nbsp;20:40&nbsp;&nbsp;iphone<br/>drwxr-xr-x&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp; taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;00:38&nbsp;&nbsp;java<br/>drwxr-xr-x&nbsp;&nbsp;94&nbsp;&nbsp;&nbsp;&nbsp; taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;16384&nbsp;&nbsp;2012-04-17&nbsp;&nbsp;20:01&nbsp;&nbsp;linux<br/>drwxr-xr-x&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-10&nbsp;&nbsp;19:29&nbsp;&nbsp;math<br/>drwxr-xr-x&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-17&nbsp;&nbsp;15:37&nbsp;&nbsp;mysql<br/>drwxr-xr-x&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2011-10-19&nbsp;&nbsp;17:04&nbsp;&nbsp;nosql<br/>drwxr-xr-x&nbsp;&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp; taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-16&nbsp;&nbsp;12:54&nbsp;&nbsp;other<br/>drwxr-xr-x&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-07&nbsp;&nbsp;14:03&nbsp;&nbsp;perl<br/>drwxr-xr-x&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;00:18&nbsp;&nbsp;python<br/>drwxr-xr-x&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-03&nbsp;&nbsp;22:50&nbsp;&nbsp;ruby<br/>drwxr-xr-x&nbsp;&nbsp;52&nbsp;&nbsp;&nbsp;&nbsp; taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;00:59&nbsp;&nbsp;search-engine<br/>drwxr-xr-x&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-15&nbsp;&nbsp;00:23&nbsp;&nbsp;software-engineering<br/>drwxr-xr-x&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2010-10-11&nbsp;&nbsp;22:56&nbsp;&nbsp;svnroot<br/>drwxr-xr-x&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;4096&nbsp;&nbsp; 2012-04-14&nbsp;&nbsp;20:33&nbsp;&nbsp;web<br/>drwxr-xr-x&nbsp;&nbsp;66&nbsp;&nbsp;&nbsp;&nbsp; taoshanwen&nbsp;&nbsp;taoshanwen&nbsp;&nbsp;12288&nbsp;&nbsp;2012-04-17&nbsp;&nbsp;23:47&nbsp;&nbsp;work<br/>11.2 fold <br/>将一个比较长的文本行输出进行"折行". <br/><br/>11.3 fmt <br/>将输入按照指定宽度进行折行, 功能较fold强大些 <br/><br/>12 微语言 <br/>下面介绍文本处理中两个最强大的命令sed和awk, 它们已经具有一些程序设计语言的特征了, 特别是awk, 所以, 我们的脚本中, 放眼望去, 皆是awk阿. 熟练掌握这两个命令, 你的文本处理功力将会极大的提升阿. <br/><br/>12.1 sed (Stream EDitor) <br/>sed是一个流编辑器, 类似ed(行编辑器, 通过各种命令编辑文件), 它提供了各种替换、删除的命令, 使得这些编辑操作能自动化起来. <br/><br/>工作流程 <br/><br/>sed维护2快内存(也可以理解为2个变量, 或者说是2个寄存器), 分别叫做 pattern space 和 hold space, sed对每行输入执行下面的循环:<br/><br/>读入输入行, 去掉尾部的换行符, 存入pattern space <br/>执行sed命令, 每条sed命令都可以有个地址与它关联, 这个地址就类似于条件语句, 只有这个条件语句通过验证时, 其对应的命令才会执行 <br/>执行完所有的sed命令后, 如果没有指定sed的-n选项, 将会打印pattern space的内容, 然后再输出换行符. 最后继续读入下一行, 进行下一次的循环 <br/>每次循环开始时, pattern space的内容会被清空, hold space则不会 <br/><br/>地址格式 <br/><br/>sed地址可以具有以下的形式:<br/><br/>NUMBER <br/><br/>指定执行命令的行号, 只有在这行, 对应的命令才会被执行, 行号从1开始, 另外, 如果没有指定-i或者-s选项的话, 所有的输入文件会被当成一个输入流, 行号就会一直累加的 <br/>FIRST~STEP <br/><br/>在FIRST、FIRST+STEP、FIRST+2*STEP、、FIRST+3*STEP行执行对应的命令 <br/>$ <br/><br/>最后一行 <br/>REGEXP <br/><br/>在匹配上正则REGEXP的行执行对应的命令, 如果REGEXP中含有/, 需要用&#92;转义 <br/>&#92;%REGEXP%<br/>在匹配上正则REGEXP的行执行对应的命令, %也可以是其他字符, 如果REGEXP中含有%, 需要用&#92;转义 <br/>/REGEXP/I, &#92;%REGEXP%I<br/>忽略大小写 <br/>/REGEXP/M, &#92;%REGEXP%M<br/>可以匹配多行, M表示multi-line <br/>如果没有指定地址的话, 表示所有行对执行命令. 还可以提供2个地址, 指定一个地址范围, 这2个地址之间以逗号分割, 比如: <br/><br/>ADDRESS1,ADDRESS2<br/>这样, 第一次匹配上ADDRESS1的行与第一次匹配上ADDRESS2的行之间的所有行都会执行对应的命令. <br/><br/>GNU sed还支持下面几种地址范围: <br/><br/>ADDR1,+N <br/><br/>匹配ADDR1, 以及接下来的N行 <br/>ADDR1,~N <br/><br/>匹配ADDR1, 直到行号为N倍数的行<br/><br/>在地址或者地址范围后加感叹号(!), 表示取反. <br/><br/>常用命令 <br/><br/>由于sed默认会打印pattern space, 所以不加任何命令的话, 就和cat一样, 打印所有的输出:<br/><br/>$ cat ab<br/>ab<br/>ab<br/>ac<br/>ad<br/>ae<br/>ac<br/>ab<br/><br/>$ sed "" ab<br/>ab<br/>ab<br/>ac<br/>ad<br/>ae<br/>ac<br/>ab<br/>d <br/><br/>删除pattern space, 立即进入下一轮循环. <br/><br/>ls输出的时候, 第一行有个摘要, 如果不想显示的话, 这样:<br/><br/>ls -l &#124; sed 1d<br/>p <br/><br/>打印pattern space. <br/><br/>输出文件ab第5到第10行:<br/><br/>sed -n 5,10p ab<br/>q [EXIT-CODE] <br/><br/>立即以返回码EXIT-CODE(默认为0)退出sed, 如果没有加-n选项的话, 当前的模式空间也会打印出来. <br/><br/>如果文件很大的话, 下面的方法输出文件ab第5到第10行会快很多:<br/><br/>sed -n "5,10p; 10q" ab<br/>n <br/><br/>如果没有加-n的话, 打印模式空间, 然后直接进入下一轮循环. <br/><br/>不打印第18行:<br/><br/>sed -n "p; 18n"<br/>&#123; COMMANDS &#125; <br/><br/>一组命令, 这组命令共用同一个地址. <br/><br/>打印第8行:<br/><br/>sed -n "8 &#123;p; q&#125;"<br/>s/REGEXP/REPLACEMENT/FLAGS <br/><br/>这个命令估计是大家用的最多的命令了. 前面几个命令大家不知道的情况下, 可能通过其他命令解决了, 但是这个命令的功能除了awk, 其他的做不了, 而sed比awk更简洁.<br/>这个命令主要是对pattern space进行替换, 对匹配REGEXP的部分用REPLACEMENT进行替换, 用来分割的/可以由其他字符组成, 比如s:REGEXP:REPLACEMENT:FLAGS. REPLACEMENT可以由原始的字符组成, 也可以由下面带有特殊意义的串组成:<br/><br/>& <br/><br/>匹配REGEXP的部分 <br/>&#92;d <br/><br/>d为1-9的数字, &#92;d表示REGEXP中第d个括号匹配的部分, 比如REGEXP为:<br/><br/>a(..(..))<br/>pattern space为abcde, 那么&#92;1为bcde, &#92;2为de <br/><br/>&#92;L <br/><br/>把REPLACEMENT中的字符变成小写, 直到遇到&#92;U和&#92;E. 比如:<br/><br/>$ cat ab<br/>AB<br/>AB<br/>ac<br/>ad<br/>ae<br/>ac<br/>AB<br/><br/>$ sed -r 's/(AB)/&#92;L&#92;1YYY/' ab<br/>abyyy<br/>abyyy<br/>ac<br/>ad<br/>ae<br/>ac<br/>abyyy<br/>上例中, 本来&#92;1应该是AB, 但是&#92;L把它全变成小写了. 而且后面的YYY也变成小写了. <br/><br/>&#92;l <br/><br/>把下一个字符变成小写 <br/>&#92;U <br/><br/>把REPLACEMENT中的字符变成大写, 直到遇到&#92;L和&#92;E. <br/>&#92;u <br/><br/>把下一个字符变成大写 <br/>&#92;E <br/><br/>结束&#92;L和&#92;U的作用<br/><br/>s命令后的FLAGS可以由下面几种: <br/><br/>g <br/><br/>s命令默认只替换第一个匹配, g可以让它全部替换 <br/>NUMBER <br/><br/>替换第NUMBER个匹配 <br/>p <br/><br/>如果发生了替换, 打印模式空间. <br/><br/>搜索文件ab中xxx并替换成yyy打印出来:<br/><br/>sed s/xxx/yyy/p ab<br/>i, I <br/><br/>正则匹配忽略大小写 <br/>y/SOURCE-CHARS/DEST-CHARS/ <br/><br/>类似tr命令, 用DEST-CHARS对应的字符替换出现在SOURCE-CHARS中的字符. 和s命令一样, 分隔符/也可以是其他字符.<br/><br/>= <br/><br/>打印行号. 下面的命令类似grep -n:<br/><br/>sed&nbsp;&nbsp;-n '/xxx/ &#123;=; p&#125;'<br/>高级命令 <br/><br/>h <br/><br/>用pattern space替换hold space <br/>H <br/><br/>先在hold space追加换行符, 再往hold space追加pattern space <br/>g <br/><br/>用hold space替换pattern space <br/>G <br/><br/>先在pattern space追加换行符, 再往pattern space追加hold space <br/>x <br/><br/>交换pattern space和hold space的内容 <br/>D <br/><br/>删除模式空间的第一行. 如果模式空间中还有内容的话, 开始进入下一轮循环, 但不读入输入. 如果没有内容的话, 读入输入并进行下一轮循环. <br/>N <br/><br/>追加换行符到pattern space, 并读入下一行输入追加到pattern space, 如果已经没有任何输入, 直接退出sed, 不再处理任何命令. <br/>P <br/><br/>大写p, 打印pattern space第一行 <br/>z <br/><br/>清空pattern space<br/><br/>专家命令 <br/><br/>: LABEL <br/><br/>设定标签, 类似C语言中设定一个标签, 然后可以goto之 <br/>b [LABEL] <br/><br/>跳转到标签, 如果没有提供标签的话, 直接进入下一轮循环 <br/>t [LABEL] <br/><br/>这轮循环中, 如果s命令替换成功过, 则跳转到标签. 如果没有提供标签的话, 直接进入下一轮循环 <br/>T LABEL <br/><br/>和t LABEL相反, s命令替换失败, 才跳转到标签<br/><br/>命令选项 <br/><br/>-n, –quiet, –silent <br/><br/>禁止自动打印pattern space <br/>-i[SUFFIX], –in-place[=SUFFIX] <br/><br/>原地编辑文件, 文本修改后会直接影响到输入文件 <br/>-r, –regexp-extended <br/><br/>启用扩展正则, 默认是基础正则 <br/>-s, –separate <br/><br/>把每个文件当作单独的输入流, 而不是一个输入流<br/><br/>给我一个寄存器, 我可以干好多事 <br/><br/>各位看完上面所说的sed命令后, 是不是觉得sed只能做一些替换、删除等操作， 为什么称为微语言呢, 我之所以把它归到微语言这一类是有原因的, 它具有下面几个语言的特征:<br/><br/>有条件判断能力, sed的地址就是一种条件判断, 还有标签命令也是条件判断 <br/>有流程控制能力, 标签命令就可以做到 <br/>有变量, 虽然很少, 只有2个, 但是仍然可以干好多事了, 看下面的例子 <br/>更多的例子参加sed info <br/><br/>tac <br/><br/>模拟tac<br/><br/>sed -n '1!G; $p; h'<br/>为数字字串增加逗号分隔符号， 将1234567变为1,234,567 <br/><br/>sed -r ':a; s/(.*[0-9])([0-9]&#123;3&#125;)/&#92;1,&#92;2/; ta' <<< 124523536543652<br/>12.2 awk (Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan.) <br/>awk是文本处理的利器, 前面那些命令能干的事它都能搞定. <br/><br/>工作流程 <br/><br/>awk的工作方式有点类似sed, sed是地址+命令, awk则是pattern+action, pattern是要匹配的模式, action是要执行的命令, pattern可以由下面几种形式:<br/><br/>BEGIN <br/><br/>awk程序开始处理输入时 <br/>END <br/><br/>awk程序结束处理输入时 <br/>BEGINFILE <br/><br/>awk程序开始处理每个文件时 <br/>ENDFILE <br/><br/>awk程序结束处理每个文件时 <br/>regular expression <br/>relational expression <br/><br/>关系表达式 <br/>pattern && pattern <br/>pattern &#124;&#124; pattern <br/>pattern ? pattern : pattern <br/>(pattern) <br/>! pattern <br/>pattern1, pattern2 <br/>action要以大括号括起来, 比如: <br/><br/>awk '0&#123;print&#125; 1&#123;print&#125;' .emacs<br/>内置变量 <br/><br/>ARGC <br/><br/>awk输入参数的个数, 不包括awk自己 <br/>ARGV <br/><br/>命令行参数 <br/>ARGIND <br/><br/>当前处理的文件在ARGV中的位置, ARGV[ARGIND]表示当前正在处理的文件, 可以通过这个变量来对不同的输入文件做不同的处理 <br/>FNR (File Number Record) <br/><br/>当前文件的记录总数 <br/>NR (Number Record) <br/><br/>目前处理的记录总数 <br/>NF (Number of Field)<br/><br/>当前记录的字段数 <br/>网络编程 <br/><br/>awk能开发网络程序, 你相信吗?<br/><br/>$ cat test.awk<br/>#!/usr/bin/awk -f<br/><br/>BEGIN &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;str = "GET /index.html HTTP/1.1&#92;r&#92;nHost: www.baidu.com&#92;r&#92;n&#92;r&#92;n"<br/>&nbsp;&nbsp;&nbsp;&nbsp;print str &#124;& "/inet/tcp/0/www.baidu.com/80"<br/>&nbsp;&nbsp;&nbsp;&nbsp;"/inet/tcp/0/www.baidu.com/80" &#124;& getline<br/>&nbsp;&nbsp;&nbsp;&nbsp;print<br/>&#125;<br/><br/>$ awk -f test.awk<br/>HTTP/1.1 200 OK<br/>陷阱 <br/><br/>tolower/toupper <br/><br/>和tr一样, 这2个函数也是对字节进行处理<br/><br/>判断元素是否存在 <br/><br/>你是否这样判断某元素是否存在于某数组:<br/><br/>if (a[e] != 2) &#123; ... &#125;<br/>如果输入很大的话, 过会你就会发现你的awk占了很多内存, 原因就是a[e]的时候, 如果awk发现a中没有e, 就会把e插入到a中, 这样一来内存自然越来越大, 正确的判断方法是: <br/><br/>if (!(e in a)) &#123; ... &#125;<br/>用过python的朋友可能会这样写: <br/><br/>if (e not in a) &#123; ... &#125;<br/>很不幸, 没有这样的语法, 而且还不报错, 我猜awk把e not连接成一个字符串了… <br/><br/>13 语言 <br/>a2p <br/>s2p <br/>perl <br/>python <br/>14 实例 <br/>14.1 我的正则会数学 <br/>multi-sort <br/>15 参考文献 <br/>相关命令的info及coreutils的<a href="http://www.gnu.org/software/coreutils/manual/coreutils.pdf" target="_blank">info</a> <br/><a href="http://www.tsnc.edu.cn/default/tsnc_wgrj/doc/abs-3.9.1_cn/html/textproc.html" target="_blank">高级Bash脚本编程指南: 文本处理命令</a><br/><a href="http://www.cosc.brocku.ca/~taa/papers/abou-assaleh_csci6306a.pdf" target="_blank">Survey of Global Regular Expression Print (GREP) Tools </a><br/>Tags - <a href="http://www.zhanghaijun.com/tags/linux/" rel="tag">linux</a>
]]>
</description>
</item><item>
<link>http://www.zhanghaijun.com/post//#blogcomment</link>
<title><![CDATA[[评论] Linux下文本的高效处理]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.zhanghaijun.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>