sed
流编辑器
执行步骤:
- 一次从输入中读取一行数据
- 根据编辑器命令匹配数据
- 按照命令修改流中的数据
- 将新的数据输出到STDOUT
sed语法:
sed options script file
options支持如下:
- -e script 处理输入时, 将script中的命令添加到已有命令
- -f file 在处理输入时, 将file中指定的命令添加到已有命令
- -n 不产生命令输出, 使用print命令完成输出
用法
命令行定义编辑命令
echo "This is a test" | sed 's/test/big test/'
# 输出This is a big test
$ cat data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$ sed 's/dog/cat/' data1.txt
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
sed默认不会修改原来的文件
命令行执行多个编辑器命令
sed -e 's/brown/green/; s/dog/cat/' data1.txt
The quick green fox jumps over the lazy cat.
The quick green fox jumps over the lazy cat.
The quick green fox jumps over the lazy cat.
The quick green fox jumps over the lazy cat.
文件中读取编辑器命令
$ cat script1.sed
s/brown/green/
s/fox/elephant/
s/dog/cat/
$ sed -f script1.sed data1.txt
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
awk
编程语言, 可以做:
- 定义变量保存数据
- 使用算术和字符串操作来处理数据
- 使用流程结构 if , 循环
- 数据布局
语法:
awk options program file
options可以如下:
- -F fs : 字段分隔符
- -f file : 从指定的文件中读取程序
- -v var=value : 定义变量及其默认值
- -mf N : 定义数据文件的最大字段数
- -mr N : 定义数据文件的最大数据行数
- -W keyword : 定义awk的兼容模式或警告等级
用法
从命令行读取程序脚本
$ awk '{print "Hello world!"}'
# 输入数据则输出"Hello world!"
# 输入EOF字符则中断该程序
使用数据字段变量
awk处理行数据时根据字段分隔符(默认为任意空白字符)将数据分成多个字段, 这些字段可以用数据字段变量标识:
- $0 : 整个文本行
- $1 : 第一个数据字段
- $2 : 第2个数据字段
- $n : 第n个数据字段
-F选项可以指定字段分隔符
$ cat data.txt
One line of test text.
Two lines of test text.
Three lines of test text.
$ awk '{print $1}' data.txt
One
Two
Three
$ awk -F: '{print $1}' /etc/passwd
# 使用-F指定字段分隔符
daemon
bin
sys
sync
games
man
lp
mail
news
uucp
proxy
www-data
backup
list
irc
gnats
nobody
_apt
systemd-timesync
systemd-network
systemd-resolve
messagebus
_rpc
程序脚本中使用多个命令
多条命令中间带分号
$ echo "My name is Rich" | awk '{$4="Christine"; print $0}'
My name is Christine
$ awk '{$4="data"; print $0}' data.txt
One line of data text.
Two lines of data text.
Three lines of data text.
从文件中读取程序
$ cat script2.gawk
{print $1 "'s home directory is " $6}
$ awk -F: -f script2.awk /etc/passwd
root's home directory is /root
daemon's home directory is /usr/sbin
bin's home directory is /bin
sys's home directory is /dev
sync's home directory is /bin
games's home directory is /usr/games
man's home directory is /var/cache/man
$ cat script3.gawk
{
text="'s home directory is "
print $1 text $6
}
处理数据前运行脚本
$ cat data3.txt
Line 1
Line 2
Line 3
$ awk 'BEGIN{print "The data3 File Contents:"} {print $0}' data3.txt
The data3 File Contents:
Line 1
Line 2
Line 3
处理数据后运行脚本
$ awk 'BEGIN{print "The data3 File Contents:"} {print $0} END{print "End of File"}' data3.txt
The data3 File Contents:
Line 1
Line 2
Line 3
End of File
使用变量
内建变量和自定义变量
内建变量
字段变量, 记录分隔符变量
[ 字段变量 ]
表示: $0, $1, … $n
控制: 字段分隔符, -F指定, FS内建变量指定
[ 记录分隔符变量 ]
- FIELDWIDTHS 由空格分割的数字, 定义每个数据字段确切宽度
- FS : 输入字段分隔符
- RS : 输入记录分隔符
- OFS : 输出字段分隔符
- ORS : 输出记录分隔符
OFS用于print输出时字段的间隔
$ cat data1.txt
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,data32,data33,data34,data35
$ awk 'BEGIN{FS=","} {print $1,$2,$3}' data1.txt
data11 data12 data13
data21 data22 data23
data31 data32 data33
$ awk 'BEGIN{FS=",";OFS="-"} {print $1,$2,$3}' data1.txt
data11-data12-data13
data21-data22-data23
data31-data32-data33
$ cat data1b.txt
1005.3247596.37
115-2.349194.00
05810.1298100.1
$ awk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data1b.txt
1005.3247596.37
115-2.349194.00
05810.1298100.1
$ cat data2.txt
Riley Mullen
123 Main Street
Chicago, IL 60601
(312)555-1234
Frank Williams
456 Oak Street
Indianapolis, IN 46201
(317)555-9876
Haley Snell
4231 Elm Street
Detroit, MI 48201
(313)555-4938
$ awk 'BEGIN{FS="\n";RS=""} {print $1,$4}' data2.txt
Riley Mullen (312)555-1234
Frank Williams (317)555-9876
Haley Snell (313)555-4938
数据变量, 一些环境影响的变量
- ARGC : 当前命令行参数个数
- ARGIND : 当前文件再ARGV中的位置
- ARGV : 包含命令行参数的数组
- CONVFMT : 数字的转换格式, 默认为%.6g
- ERRNO : 错误号
- FILENAME : 输入数据文件的文件名
- FNR : 当前数据文件中的数据行数
- IGNORECASE : 非零忽略字符串大小写
- NF : 字段总数
- NR : 已处理的输入记录数
- OFMT : 数字的输出格式, 默认为%.6g
- RLENGTH : match函数匹配的子字符串的长度
- RSTART : match函数匹配的子字符串的起始位置
$ awk 'BEGIN{FS="\n";RS=""} {print FNR,NF,NR,$NF}' data2.txt
1 4 1 (312)555-1234
2 4 2 (317)555-9876
3 4 3 (313)555-4938
自定义变量
变量不能以数字开头, 区分大小写
- 在脚本中给变量赋值
支持算术运算(%, ^, **)
$ awk 'BEGIN{testing="This is a test";print testing;testing=45;print testing;testing=testing*2+3;print testing}' data.txt
This is a test
45
93
- 在命令行上给变量赋值
只有-v命令行上的变量才能在BEGIN代码块使用; 而且-v n=2 必须在代码块之前调用
$ awk '{print n}' n=2 data.txt
$ awk -v n=2 -v a=3 'BEGIN{print n,a}' data.txt
2
2
2
2 3
使用模式
正则表达式匹配
匹配操作符匹配特定的数据字段
排除匹配数据字段
# 正则表达式匹配
$ awk 'BEGIN{FS=","} /11/{print $1}' data1.txt
# 匹配操作符将正则表达式限定在特定的数据字段
$ awk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}' data1.txt
# 排除匹配
$ awk -F: '$1 !~ /nginx/{print $1, $NF}' /etc/passwd
# 数学表达式 == <= < >= >
$ awk -F: '$4 == 0{print $1}' /etc/passwd
data11
data21,data22,data23,data24,data25
systemd-timesync /usr/sbin/nologin
systemd-network /usr/sbin/nologin
systemd-resolve /usr/sbin/nologin
messagebus /usr/sbin/nologin
_rpc /usr/sbin/nologin
sshd /usr/sbin/nologin
statd /usr/sbin/nologin
root
内建函数
内建函数包括数学函数, 字符串函数和时间函数
时间函数
- mktime(datespec) : 将YYYY MM DD HH MM SS [DST]格式指定的容器转换成时间戳
- strftime(format[, timestamp]) : 将当前时间戳转换为格式化日期, format与date()一致
- systime() : 返回当前时间的时间戳
# 提供数学, 字符串, 时间函数
awk 'BEGIN{date=systime();day=strftime("%Y/%m/%d %H:%M:%s");print day}' data.txt
实例
替换每天对应的数据
awk -v date=$(date +%Y/%m/%d) -v cache=$_sum '$1==date{$2=cache} {print $0}' $_file >$_tmp_file && mv -f $_tmp_file $_file && rm -f $_tmp_file
