渊源

Unix 系统最早的时候有一个叫做 ed 的编辑器, ed 影响产生了很多很多其他编辑器, 比如 ex, 基于 ex 又出现了 VIM(底层其实是 ex, 执行冒号开始的命令比如 :32p 其实执行的就是 ex 命令).

sed 其实就是 stream ed 的意思, 显然 sed 是脱胎于 ed 的.

awk 虽然并非直接脱胎于 ed, 但是也多多少少吸取了其中一些设计思想.

共同点

sedawk 两者基本都是如下运行方式, 即前半段用于指定范围, 后半段用于动作:

范围 + 动作


范围部分存在时, 则只对指定范围内的内容做处理.

范围可以省略. 若范围不存在, 则对每一行执行动作部分内容.

动作部分不可省略.


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.

Comments
Write a Comment