sed和awk的学习

Sed和AWK都是命令行里处理文本的神器,它们都是面向行的,从标准输入或者文件中读取内容,一行行执行,然后到标准输出,直到文件结尾(EOF)。

Sed

sed 语法格式

Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

-n, --quiet, --silent
suppress automatic printing of pattern space
-e script, --expression=script
add the script to the commands to be executed
-f script-file, --file=script-file
add the contents of script-file to the commands to be executed
--follow-symlinks
follow symlinks when processing in place
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
-l N, --line-length=N
specify the desired line-wrap length for the `l' command
--posix
disable all GNU extensions.
-r, --regexp-extended
use extended regular expressions in the script.
-s, --separate
consider files as separate rather than as a single continuous
long stream.
-u, --unbuffered
load minimal amounts of data from the input files and flush
the output buffers more often
-z, --null-data
separate lines by NUL characters
--help display this help and exit
--version output version information and exit

If no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret. All
remaining arguments are names of input files; if no input files are
specified, then the standard input is read.

GNU sed home page: <http: www.gnu.org="" software="" sed="">.
General help using GNU software: <http: www.gnu.org="" gethelp="">.
E-mail bug reports to: <bug-sed@gnu.org>.
Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.
</bug-sed@gnu.org></http:></http:>

执行多个指令的方法

使用单个指令时甚至可以不指定-e选项

  • 使用分号

    sed 's/You/I/;s/should/will/' testfile
  • 在每个指令面前使用参数-e来指明是指令

    sed -e 's/You/I/' -e 's/should/will/' testfile
  • 使用Bourne shell的分行指令功能:在输入单引号后回车,出现多行的输入提示符’>’

    $ sed 's/You/I/
    >s/should/will/
    >' testfile
  • 如果指令太多,都输在命令行是不现实的,可以使用脚本文件,然后使用-f来设置,如脚本文件script

    s/You/I/
    s/should/will/

    sed 命令

    sed -f script testfile
  • 如果使用-f还想使用指令,则不能省略-e

    sed -e 's/look at/see/' -f script testfile

全局g

sed默认是是将命令用于每行的,而如果加上全局g则意思是对行做全局处理,如testfile内容

james kelvin kevin beston
tom jerry james carry iris james

指令

sed 's/james/ivan/' testfile

输出

ivan kelvin kevin beston
tom jerry ivan carry iris james

可看得出每行的第一个james都替换成了james.加上全局g再看指令

sed 's/james/ivan/g' testfile

输出

ivan kelvin kevin beston
tom jerry ivan carry iris ivan

地址匹配

sed命令可以指定零个、一个或两个地址,每个地址都是一个描述模式、行号或者行寻址符号的正则表达式。

  • 如果没有制定地址,那么命令将应用于每一行
  • 如果只有一个地址,那么命令应用于这个地址匹配的任意行。
  • 如果指定了由逗号分隔的两个地址,那么命令应用与匹配第一个地址的第一行和它后面的行,知道匹配第二地址的行(包括此行)。
  • 如果地址后面有感叹号(!),那么命令就应该用于不匹配该地址的所有行。

分组命令

sed使用大括号({})将一个地址嵌套在另一个地中,或在相同的地址上应用多个命令。常用的应用场景如在指定的范围行进行操作,如

sed '2,4{
>s/james/ivan/
>}' testfile

也可以使用脚本文件,但都必须遵循这样的规则:左大括号必须在行末,而且右大括号本身必须单独占一行,而且要确保在右大括号后没有空格。

大小写替换

\u是把后面紧跟的串首字母大写,而\U则是全部大写;同理\l和\L一样的逻辑,如文本name中内容为”My name is zhaiqianfeng.”,则

sed 's/\b[a-z]/\u&/g'

输出

My Name Is Zhaiqianfeng.

其中”&”表示匹配的字符串,也可以用反向引用达到同样的效果

sed -r 's/\b[a-z]/\u\0/g'

sed的命令梳理

  • 注释:使用”#”来注释行
  • 替换
    语法

    [address]s/pattern/replacement/flags

    flags可以是

    • n 1到512之间的一个数字,表示对文本模式中指定模式第n次出现的情况进行替换
    • g 对模式空间的所有出现的情况进行全局更改,而没有g通常只有第一次出现的情况被取代
    • p 打印模式空间的内容
    • w file 将模式空间的内容写到文件中

    replacement

    • & 用正则表达式匹配的内容进行替换
    • \n 反向引用匹配
    • \转义符
  • 删除:删除命令比较简单直接用d即可。
  • 追加、插入和更改

    #追加
    [line-address]a\
    text

    #插入
    [line-address]i\
    text

    #更改
    [line-address]c\
    text

    追加在匹配行之后,插入在匹配行之前,更改是匹配行;如果text是多行,则除最后一行都必须使用\结束。

  • 列表
    列表命令(l)用于显示模式空间的内容,将非打印的字符显示为两个数字的ASCII代码。其功能类似于vi中的列表命令(:l),可以使用该命令来检测输入中的“不可见”字符。

    sed -n 'l' testfile
  • 转换
    转换命令是y,这个命令按位置将匹配的每个字符依次替换相应的

    sed 'y/jk/12/' testfile

    将所有的j、k分别替换为1、2

  • 打印:打印命令使用p
  • 打印行号
    使用=打印行号

    sed -n '/james/=' testfile </pre>
    但打印行号不能对一个范围内的行进行操作。
    <pre class="prettyprint lang-js"> sed -n '/james/{
    =
    p
    }' testfile
  • 下一步
    命令n(next)输出模式空间的内容,然后读取输入的下一行

    sed -n '/james/{
    next
    p
    }' testfile
  • 读取和写入
    读(r)和写(w)命令用于直接处理文件,语法如下

    [line-address]r file
    [address]w file

    例如把文件a的内容插入到匹配行下面

    sed '/james/r a' testfile
  • 退出

    [line-address]q

    如读出前2行

    sed '2q' testfile

AWK

AWK的语法

Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-D[file] --debug[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-i includefile --include=includefile
-l library --load=library
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-M --bignum
-N --use-lc-numeric
-o[file] --pretty-print[=file]
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
gawk '{ sum += $1 }; END { print sum }' file
gawk -F: '{ print $1 }' /etc/passwd

尽管awk与sed的命令结构相似,都由模式和过程两部分组成,但过程本身却大不相同。在通常情况下,awk将每个输入行解释为一条记录,而将一行上的每个单词(由空格或制表符分隔)解释为每一个字段(可以改变这些默认设置).awk允许在模式或过程中引用这些字段。$0代表整个记录。

awk '{print $1}' testfile

上述指令表示打印每个记录的第一个字段,由于没有使用模式,所以上面的指令适用所有行。

awk '/should/' testfile

由于制定了匹配模式,所以打印匹配这种模式的每一行。既使用匹配模式又使用指令的awk

awk '/should/{print $1}' testfile

设备分隔符

可以用-F来设置分隔符,比如设置成逗号

awk -F , '{print $1}' testfile

备注

$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$ 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(“ “)包含时,与 $
稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

翟前锋 wechat
欢迎订阅我的微信公众号:zhaiqianfeng!