渊源
Unix 系统最早的时候有一个叫做 ed
的编辑器, ed
影响产生了很多很多其他编辑器, 比如 ex
, 基于 ex
又出现了 VIM
(底层其实是 ex
, 执行冒号开始的命令比如 :32p
其实执行的就是 ex
命令).
sed
其实就是 stream ed 的意思, 显然 sed
是脱胎于 ed
的.
awk
虽然并非直接脱胎于 ed
, 但是也多多少少吸取了其中一些设计思想.
共同点
sed 和 awk 两者基本都是如下运行方式, 即前半段用于指定范围, 后半段用于动作:
范围部分存在时, 则只对指定范围内的内容做处理.
范围可以省略. 若范围不存在, 则对每一行执行动作部分内容.
动作部分不可省略.
sed
范围一般是正则表达式, 比如 /^regular$/
, 表示只包含 regular 字样的行.
也可以是行号等, 比如 50,60
, 表示第 50 到 60 行.
还可以是二者的组合, 比如 50,/regular/
, 表示从 50 行开始到下一个包含 regular 字样的行.
日常使用中最常见的是正则表达式的方式或者省略范围.
动作常用的可以是 s
(替换), p
(打印), d
(删除) 等.
/reqular/p
, 打印包含 regular 字样的行.
50,60d
, 删除第 50 到 60 行.
/regular/s/LA/Los Angeles/g
, 在包含 regular 字样的行中, 将 LA 替换为 Los Angeles.
s/like/LIKE/g
, 省略了范围, 将每一行中的 like 大写.
sed 基本语法:
# 一般写法
/regular/s/before/after/g
50,60s/before/after/g
50,60p
# 包含范围和动作
# /Sebastopol/ 用于匹配, 仅对含有 Sebastopol 的行做处理
# s/CA/California/g 是动作, 将所有 CA 替换为 California
/Sebastopol/s/CA/California/g
# 可以省略匹配部分, 即不写 /Sebastopol/, 意味着对匹配行没有限制, 任何行都执行后续动作
s/CA/California/g
常见命令行语法:
# 只有一个命令的时候, 可以省略 -e
sed -e command1 -e command2 target-file
cat target-file | sed -e command1 -e command2
# 使用 -f 指定 sed 脚本文件
sed -f sed-script target-file
cat target-file | sed -f sed-script
# 使用 sed 实现类似 cat 的功能(其实没啥用, 仅为了展示效果)
# 使用 -n 关闭 sed 默认的打印功能, 不指定范围, 直接使用 p 动作打印每一行
cat file | sed -n p
# 使用 sed 打印特定行
cat file | sed -n /regular/p
cat file | sed -n 50,60p
# 使用 sed 进行替换(最常见用法)
cat file | sed s/like/LIKE/g
cat file | sed /regular/s/CA/California/g
cat file | sed 50,60s/CA/California/g
# 使用扩展正则表达式
cat file | sed -n -E /\bregular\b/p
awk
/范围/ {动作}
范围通常是正则表达式, 可以省略.
若指定范围, 则只对范围内的行执行动作:
awk '/regular/ { print $1 }'
, 打印包含 regular 字样的行的第一个 field.
若省略范围, 则对每一行执行动作:
awk '{ print $1 }'
, 打印每一行的第一个 field.
动作通常是打印该行中某些部分.
例如 awk '{ print $1 }'
就是打印按空格隔开的各项中的第一项.
通常见到的 awk 命令后面都跟着双引号和大括号'{}'
, 这是因为 awk
命令通常包含很多符号, 为避免这些内容提前被 shell 解释, 需要用单引号包裹起来(单引号中内容不会转义), 作为一个单一参数传给 awk. 而大括号是因为 awk 的动作部分必须显示的使用大括号包裹起来.
常见用法:
# 包含匹配和动作, 仅对含有 regular 字样的行做动作
# 动作是打印改行第一列
awk '/regular/ { print $1 }'
# /regular/ 可省略, 对所有行做动作
# 没有匹配是 awk 中很常见的写法
# 单引号包裹是避免 shell 提前对 $1 等内容进行解释
# 大括号不可省略, 大括号是动作语法的一部分
awk '{ print $1 }'
备忘
one-liner:
perl -lane 'command'
sed -e 'command'
awk 'command'
awk simulates arrays with multiple indices by treating a comma-separated list of indices as a single string. However, because commas might well occur in the index values themselves, awk replaces the index-separator commas by an unprintable string stored in the built-in variable SUBSEP.