共计 22619 个字符,预计需要花费 57 分钟才能阅读完成。
[TOC]
正则表达式与文本搜寻
元字符
.
匹配任意单个字符(单行模式下不匹配换行符)*
匹配前一个字符任意次[]
匹配范畴内任意一个字符^
匹配结尾$
匹配结尾\
本义前面的特殊字符
扩大元字符
+
先前的项能够匹配一次或屡次。?
先前的项是可选的,最多匹配一次。|
匹配后面或前面的正则表达式, “ 或 ”()
分组
反复
一个正则表达式前面能够追随多种反复操作符之一。{n} 先前的项将匹配恰好 n 次。{n,} 先前的项能够匹配 n 或更屡次。{n,m} 先前的项将匹配至多 n 词,然而不会超过 m 次
find 命令
递归地在目录中查找文件
find [门路...] 表达式
表达式
查找范畴
-maxdepth <level> # 目录递归最大层数
-mindepth <level> # ?
按文件名查找
-name "模式" # 残缺匹配根本的文件名, 应用 "通配符" 匹配根本的文件名
-regex "模式" # 残缺匹配整个门路(并非单单匹配文件名), 应用 "正则" 匹配根本的文件名
-iregex "模式" # 残缺匹配整个门路(并非单单匹配文件名) , 应用 "正则" 匹配根本的文件名, 但不辨别大小写
-regextype <reg_type> # 扭转正则表达式语法, 可选: emacs (this is the default), posix-awk, posix-basic, posix-egrep and posix-extended
按文件类型查找
-type 类型 # b 块设施, c 字符设施, d 目录, p 命名管道, f 一般文件, l 符号链接, s 套接字
按工夫查找
# 数字参数
# +n 在这之前的
# -n 在这之后的
# n 正好处于该时刻
-daystart # 从当日 0 点为基准, 而不是以后时刻, 影响下述几种工夫类型.
-atime <n> # Access, 最初拜访工夫, 单位为天(但理论是以以后工夫为基准)
-ctime <n> # Change, 文件 i 节点批改工夫, 单位为天
-mtime <n> # Modify, 文件内容批改工夫, 单位为天
-amin <n> # 相似 atime, 但单位是分钟
-ctim <n> # 相似 ctime, 但单位是分钟
-mmin <n> # 相似 mtime, 但单位是分钟
按大小
-size <n> # 默认单位是块(512 字节), 反对 k(KB), M(MB), G(GB), 能够用 + - 或无符号, 意义同下面的按工夫查找.
按归属
-user <user> # 按属主
-uid <uid> # 按属主的 id
动作
-exec 操作 \; # 执行时无需确认, {} 作为转义字符会被替换成查找的文件
-ok 操作 \; # 相似 -exec, 然而每次操作都会提醒确认
运算符(按优先级从高到低排序)
() # 强制优先
! < 表达式 > # 逻辑非, 对 < 表达式 > 后果取反, 即不匹配前面条件, 比方 ! -name 示意不匹配指定文件名
-not < 表达式 > # 逻辑非, 同 ! < 表达式 >
< 表达式 1 > < 表达式 2 > # 逻辑与(默认), 如果前一个 < 表达式 > 执行后果为 false, 则不会执行后续 < 表达式 >
< 表达式 1 > -a < 表达式 2 > # 逻辑与, 同上
< 表达式 1 > -and < 表达式 2 > # 逻辑与, 同上
< 表达式 1 > -o < 表达式 2 > # 逻辑或
< 表达式 1 > -or < 表达式 2 > # 逻辑或
< 表达式 1 > , < 表达式 2 > # 前一个表达式的后果不影响后一个表达式的执行
cat
仅会批改 access 工夫
touch
会同时批改 access, modify, change
chmod
仅会批改 change 工夫
留神:
- 不同参数的前后程序很重要, 比方
-daystart
须要写在-atime
等之前, 否则对其不失效.
示例
# 仅删除昨天的日志
find /path/to/log -daystart -mtime 1 -exec rm -v {} \;
grep 命令
文本内容过滤(查找)
查找文本中具备关键字的一行
阐明
若未提供查找的文件名或是 - 则默认是规范输出
语法
grep [选项] 模式 文件...
grep [选项] (-e 模式 | -f 蕴含模式的文件) 文件...
选项
模式
-G, --basic-regexp # 应用根本正则(默认)
-E, --extended-regexp # 应用扩大正则
-e 模式, --regexp= 模式 # 当模式以 - 结尾时, 应应用这种形式
-v, --invert-match # 反向匹配, 只抉择不匹配的行
-i, --ignore-case # 疏忽大小写
-R, -r, --recursive # 递归地读每一目录下的所有文件。这样做和 -d recurse 选项等价。显示内容
-A <n>, --after-context=<n> # 打印匹配行的后续 n 行
-B <n>, --before-context=<n> # 打印匹配行的后面 n 行
-o, --only-matching # 只显示匹配的局部(默认是显示匹配行的所有内容)
-n, --line-number # 同时显示行号
批改显示类型, 不进行通常输入
-c # 打印匹配到多少行
-l, --files-with-matches # 打印匹配的文件名
-L, --files-without-match # 打印不匹配的文件名
留神:
- 在输出选项时尽量应用引号突围, 防止 Shell 去解释, 比方
grep \.
实际上模式是.
也就是匹配任意字符. 而grep "\."
或grep '\.'
才是匹配模式\.
在根本正则表达式中,元字符 ?, +, {, |, (, 和) 丢失了它们的非凡意义;作为代替,应用加反斜杠的 (backslash) 版本 ?, +, {, |, (, 和)。
cut 行切割
在文件的每一行提取片段
cut 选项 [FILE]...
选项
-d, --delimiter < 分隔 > # 以指定分隔符来切割, 分隔符必须是单个字符
-f, --fields <list> # 输入指定地位的字段, 用逗号分隔多个地位, 地位从 1 开始
uniq 间断反复行解决
删除排序文件中的 "间断" 反复行
默认从规范输出读取, 输入到规范输入
uniq 选项 [INPUT [OUTPUT]]
选项
-c, --count # 在首列显示反复数量
-d, --repeated # 仅显示反复的行
sort 排序
对文本文件的行排序
sort 选项 [FILE]...
选项
字段类型
-n # 依照数值排序, 默认蕴含 -b
-k #
-r # 逆向排序
-b # 疏忽结尾的空格
seq 产生数字序列
产生数字序列
语法
seq [OPTION]... LAST
seq [OPTION]... FIRST LAST
seq [OPTION]... FIRST INCREMENT LAST
tac 倒序显示
tac [选项] < 文件 =STDIN>
行编辑器
非交互式, 基于行操作的模式编辑.
sed 行编辑器
sed 是单行文本编辑器, 非交互式.
sed 的模式空间, 其根本工作形式
- 将文件以行为单位读取到内存(称作模式空间)
- 应用 sed 的每个脚本顺次对该行进行操作
- 打印模式空间的内容并清空
- 读取下一行, 反复执行上述步骤
sed 的空间示意图:
- 模式空间的内容默认会输入, 并清空
- 放弃空间的默认内容是
\n
Tip
- 应用
;
能够替换多个-e
模式空间 pattern space
s 替换命令
替换
sed [选项] '[< 寻址 >]s< 分隔符 ><old>< 分隔符 ><new>< 分隔符 >[< 标记位 >]' [文件...] # 简略示例: sed 's/old/new/'
参数
old # 反对正则表达式
分隔符 # 能够采纳 / 也能够采纳其余来防止与正则匹配内容抵触, 比方 ~ @ 等
寻址(默认是所有行)
! # 对寻址取反, eg. "2,4!d" 示意不删除 2~4 行
<n> # 只替换第 <n> 行
<n1>,<n2> # 区间: 从 <n1> 到 <n2> 这几行 eg. /12\/Apr\/2020/,/13\/Apr\/2020/ 正则同样能够应用这种区间寻址
1,<n> # 替换从开始到第 <n> 行
<n>,$ # 替换从第 <n> 到完结的这些行
/ 正则 / # 仅替换合乎此正则匹配到的行
# eg. sed '/ 正则 /s/old/new/'
# eg. sed '/ 正则 /,$s/old/new/' (正则能够和行号混用)示意从匹配到的正则那行开始到完结都替换
# 寻址能够匹配多条命令, 留神大括号. eg. /regular/{s/old/new/;s/old/new/}
# 比方 nginx 日志须要筛选出 14 号这天的: sed -n '/14\/Apr\/2020/,/15\/Apr\/2020/ p' xx.log
标记位(默认是只替换第 1 个匹配项)
/g # 替换所有匹配项(默认只替换第 1 个匹配项)
/<n> # <n> 是一个数字, 示意每行只替换第 <n> 个匹配项
/p # 打印模式空间的内容(即匹配的行), 通常会和 -n 一起应用, 如果不和 -n 一起应用, 会导致匹配的行多输入顺次.
# eg. sed -n 's/old/new/p' # 此时仅打印匹配的行
/w <file> # 将模式空间的内容 (即匹配到的行) 写入到指定文件
选项
-r, --regexp-extended # 应用扩大正则表达式, 包含圆括号分组及回调.
-e script, --expression=script # 指定多个执行脚本时, 每个脚本前用一个 -e. 能够应用 "分号" 简写
# Eg. -e 's/old1/new1/' -e 's/old2/new2/'
-f script-file, --file=script-file # 加载脚本文件
-i[< 后缀 >], --in-place[=< 后缀 >] # 批改原始文件, 当指定后缀时则会生成对应的备份文件. 也能够间接输入重定向输入到其余文件
-n, --quiet, --silent # 默认不主动打印
示例
# 应用扩大正则表达式
sed -r 's/old/new/' [文件]...
# 执行多个脚本
sed -e 's/old/new/' -e 's/old/new/' [文件]...
sed 's/old/new/;s/old/new/' # 应用分号隔开不同脚本
# 将后果写回文件保留
sed -i 's/'
sed -i,.bak 's/'
# 圆括号分组及回调
echo "a213123t" | sed -r 's/a(\d*)/b\1/g' # b213123t
d 删除命令
删除以后 "模式空间的内容", 并放弃前面的命令, 读取新的内容并从新执行 sed
扭转脚本的控制流, 读取新的输出行
(因为模式空间的内容被删除了, 因而 d 前面的脚本没法执行, 会略过)
(应用 s 替换成空内容, 但实质上这一行内容还在, 依旧会执行后续脚本, 会输入)
sed '[< 寻址 >]d' [文件...]
寻址
同 s 命令
示例
sed '1d' # 删除第一行
sed '/^\s*#/d' # 删除 # 结尾的行
a 追加命令
在匹配行的下一行插入内容
sed '[< 寻址 >]a < 插入内容 >'
示例
sed '1i haha' # 在原先第 1 行后面插入 haha
i 插入命令
在匹配行在上一行插入内容
sed '[< 寻址 >]i < 插入内容 >'
示例
sed '2i haha' # 在原先第二行后面插入 haha
c 改写命令
将匹配行替换成指定内容
指定匹配间断几行时, 只会替换 1 次 # sed '2,5c < 替换内容 >'
sed '[< 寻址 >]c < 替换内容 >'
示例
sed '2c hehe' # 将第 2 行替换成 "hehe"
r 读文件并插入 (从文件读取改写内容)
在匹配行上面别离插入指定文件中的内容
sed '[< 寻址 >]r < 文件名 >'
示例
sed '$r afile' bfile > cfile # 将 afile 内容追加到 bfile 结尾并合并成新的文件 cfile
罕用于合并多个文件
w 写文件 ?
?
sed '[< 寻址 >]w < 文件名 >'
p 打印
与 替换命令 s 的标记位 /p
不一样.
输入匹配的行(不禁止原始的输入)
sed [选项] '[< 寻址 >]p'
示例
sed -n '< 寻址 >p' # 只打印匹配的行
n 提前读入下一行, 并指向下一行
sed 'n'
示例
cat <<EOF | sed 'n'
1
2
3
4
5
EOF
# 输入(因为未作任何操作, 因而原样输入)
1
2
3
4
5
# ----------------------
cat <<EOF | sed -n 'n;p'
1
2
3
4
5
EOF
# 输入
2
4
失常模式
应用 n 命令后
应用 n 命令后
图起源: https://blog.51cto.com/studyi…
q 退出命令
遇到匹配项, 在解决完该项后退出
sed '[< 寻址 >]q'
示例
sed '2q' # 在打印完第二行后退出
sed '/root/q' # 在匹配到某一行有 root 后退出
打印前 N 行的一个比拟
sed 10q filename
读取前 10 行就退出sed -n '1,10p' filename
逐行读入全副, 只显示 1 -10 行, 更耗时.
= 打印行号
打印出以后行号(单行显示)
不影响失常的打印
sed '='
示例
echo 'a' | sed '=' # 打印后果, 第一行 "1", 第二行 "a"
多行模式空间 pattern space
多行模式空间扭转了 sed 的根本流程, 通过应用 N, P, D 读入并解决多行.
次要应答配置文件是多行的状况, 比方 json 或 xml.
综合示例
a.txt 内容如下
1
2
3
4
5
6
7
8
9
# ------------------- 示例 1 ---------------------#
sed 'N;N;s/\n/\t/g;' a.txt
1 2 3
4 5 6
7 8 9
# --------------------- 示例 2 打印梯形构造 -------------------#
# 关键在于利用 D 扭转控制流
sed -n 'P;N;s/\n/\t/;s/^/\n/;D' a.txt
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9
b.txt 内容如下
hell
o bash hel
lo bash
# -------------------- 示例 hello bash 替换成 hello sed --------------#
sed 's/^\s*//;N;s/\n//;s/hello bash/hello sed\n/;P;D;' b.txt
hello sed
hello sed
N 将下一行退出到模式空间
读取时, 将下一行退出到模式空间
两行视为同一行, 但两头有个换行符 \n
此时多行模式 . 能够匹配到除了开端的其余换行符
sed 'N'
示例
sed = < 文件 > | sed 'N;s/\n/\t/' # 在每行后面退出行号
应用 N 命令后
图起源: https://blog.51cto.com/studyi…
D 删除模式空间中的第一个字符到第一个换行符
留神
会扭转控制流, 不再执行紧随的后续命令, 会再次回到脚本的初始处(但不清空模式空间)
sed 'D'
P 打印模式空间中的第一个字符到第一个换行符
留神
仅仅是打印, 并不会删除打印的局部.
sed 'P'
放弃空间 hold space
留神:
-
放弃空间在不存储货色时, 它外面的默认内容是
\n
因而第一次个别是用
h
笼罩掉放弃空间的\n
- 放弃空间的内容只能长期存储和取出, 无奈间接批改
综合示例
# 下述多个都实现了 tac 倒序显示的成果
# 思路: 每次将本轮正确的后果保留在放弃空间
cat -n /etc/passwd | head -n 6 | sed -n '1!G;$!x;$p'
cat -n /etc/passwd | head -n 6 | sed -n '1!G;h;$p'
cat -n /etc/passwd | head -n 6 | sed '1!G;h;$!d'
cat -n /etc/passwd | head -n 6 | sed '1!G;$!x;$!d'
cat -n /etc/passwd | head -n 6 | sed -n '1h;1d;G;h;$p';
cat -n /etc/passwd | head -n 6 | sed -n '1h;1!G;h;$p';
sed '=;6q' /etc/passwd | sed 'N;s/\n/\t/;1!G;h;$!d'
# --------------------- 显示后果 --------------------#
6 sync:x:5:0:sync:/sbin:/bin/sync
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
2 bin:x:1:1:bin:/bin:/sbin/nologin
1 root:x:0:0:root:/root:/bin/bash
h 和 H 将模式空间内容寄存到放弃空间
- h 是笼罩
- H 是追加
留神: 该操作不会清空模式空间(须要清空模式空间能够用 d
)
g 和 G 将放弃空间内容取出到模式空间
- g 是笼罩
- G 是追加
留神: 该操作不会清空放弃空间
x 替换模式空间和放弃空间内容
awk 行编辑器
awk 是一种解释型编码语言, 罕用于解决文本数据.
awk 次要是对 sed 的一个补充, 罕用于在 sed 解决完后对相应后果进行调整并输入.
awk 版本
- awk: 初始版本
- nawk: new awk, 是 awk 的改良增强版
-
gawk: GNU awk, 所有 GNU/Linux 发行版都蕴含 gawk, 且齐全兼容 awk 与 nawk
理论 centos 用的就是 gawk
参考文档:
- The GNU Awk User’s Guide
网上很多教程瞎 JB 写, 倡议以官网文档???? 为准
- 精通 awk 系列
十分不错的系列教程! :+1:
- https://awk.readthedocs.io/en…
不残缺.
awk 和 sed 的区别
- awk 更像是 脚本语言
- awk 用于 “ 比拟标准 ” 的文本处理, 用于 统计数量 并调整程序, 输入指定字段.
- 应用 sed 将不标准的文本处理为 ” 比拟标准 ” 的文本
awk 脚本的流程管制
BEGIN{}
输出数据前例程, 可选{}
主输出循环END{}
所有文件读取实现例程
集体了解的执行程序
- 执行开始块(可选)
BEGIN{}
-
若存在主体块 {}
或完结块
END{}`, 则关上文件并读入数据如果文件无奈关上会在此时报错.
主体块容许存在多个, 比方依据不同的匹配模式, 写多个主体块.
- 若存在
< 寻址 >
或/pattern/
, 则会顺次匹配, 通过则对该记录执行{}
- 读完所有记录后, 执行完结块(可选)
END{}
非凡状况, 脚本只蕴含
BEGIN{}
时, 在执行 awk 命令前面传入参数(非文件名), 此时不会导致报错, 因为不会执行到步骤 2(即尝试关上文件).
如果脚本只蕴含 BEGIN{命令}
, 如同能够缩写成 awk '命令'
??
语法
语法
awk [选项] 'awk 脚本内容' [--] [文件...] # 其中任意一部分都是可选的
awk [选项] -f <awk 脚本文件 > [--] [文件...] # 不间接在命令行中书写 awk 脚本, 而是从指定文件读取
选项
-f < 脚本文件 >, --file=< 脚本文件 > # 从指定脚本文件读取 awk 脚本, 而不是默认地从第一个命令行参数读取.
-F, --field-separator < 分隔符 > # 字段分隔符能够应用正则表达式, 是空格 "", 也能够在 awk 脚本中用 FS="," 来批改这一行为
-v <var>="val", --assign <var>="val" # 间接为 awk 脚本中的变量赋值, 比方 -v suffix=yjx, 而后代码中间接就存在 suffix 这个变量了, 且值是 yjx
--dump-variables[=<file="awkvars.out">] # 将 awk 中的所有全局变量及其值导出到指定文件中.
awk 脚本的块
开始块
BEGIN {} # 非凡模式: 读取输出数据前
主体块
表达式 {} # 若匹配上才执行后续的 action
# eg.
# `$1 == "top" {}`
# `NR >= 2 {}`
# 'length($0)'
/ 正则 / {} # 正则匹配, 若匹配上才执行后续的 action
# eg.
# /^menu/ 只解决 menu 结尾的记录
# /cost/ 只解决本行内容中蕴含 "cost" 的记录
!/ 正则 / {} # 正则不匹配
组合模式 {} # 一个 组合模式 通过与(&&),或(||),非(|),以及括弧来组合多个表达式
{} # 每读取一行数据则执行后续的 action
模式 1, 模式 2 {} # 范畴模式 (range pattern) 匹配从与 模式 1 相匹配的行到与 模式 2 相匹配的行(蕴含该行)之间的所有行,对于这些输出行,执行 语句。完结块
END {} # 非凡模式: 读取结束后
主体块的 action
print 打印(若未配置则默认是 print)
next 对于本行的解决, 跳过后续步骤表达式
{...} 执行 {} 中的脚本
示例.
awk [选项] 'BEGIN{} [< 条件 >] {} END{}' 文件... # 其中任意一部分都是可选的
# BEGIN{} 输出数据前例程
# {} 主输出循环, < 寻址 > 是利用于 {} 的
# END{} 所有文件读取实现例程
awk -f < 脚本.awk> # 从文件中加载执行的命令, 留神 < 寻址 > 要和 { 写在同一行, 不然如同没失效?
# 示例 xx.awk
# BEGIN {
# ...
# }
# / 过滤条件 / {
# ...
# }
# END {
# ...
# }
字段援用
$0 # 示意记录整行
$1 $2 ... $n # 示意第 1~ 第 n 个字段
NF # 标识 $0 被宰割的字段数
$NF # 示意最初一个字段, NF 变量示意字段的数量, 比方以后共 5 个字段, 则 $NF 等价于 $5.
简略示例
awk -F ',' '{print $1,$2,$3}' filename # 逗号分隔, 打印前 3 个字段
echo "menuentry'CentOS Linux (5.5.6) 7 (Core)'--class centos" | awk -F "'"'{print $2}' # 提取出内核版本
批改字段或 NF 值的联动效应
留神以下几种操作
- 批改
$0
会依据FS
, 从新划分字段并主动赋值给$1
,$2
, … ,NF
.$0=$0
也会触发从新划分字段的操作. -
批改
$1
,$2
, … , 会依据OFS
从新生成$0
, 但不会从新宰割.即便是
$1=$1
也会触发上述操作, 当然是用NF=NF
也是能够的.# 利用该个性从新生成去除行首行尾空格, 压缩两头空格的成果 echo "a b c" | awk '{NF=NF; print $0;}' 输入 a b c
- 赋值给不存在的字段, 会新增字段并按需应用空字符串填充两头的字段,并应用
OFS
从新计算 $0 - 减少
NF
值,将应用空字符串新增字段,并应用OFS
从新计算$0
- 缩小
NF
值,将抛弃肯定数量的尾部字段,并应用 OFS 从新计算 $0
正则字面量
这里有个中央容易被坑到!!!
任何独自呈现的 /pattern/
都等价于 $0 ~ /pattern/
, 这个在将正则表达式赋值给变量时特地容易被坑, 举例:
if(/pattern/)
等价于if($0 ~ /pattern/)
a = /pattern/
等价于将$0 ~ /pattern/
的匹配返回值(0 或 1)赋值给 a/pattern/ ~ $1
等价于$0 ~ /pattern/ ~ $1
,示意用$1
去匹配 0 或 1/pattern/
作为参数传给函数时,传递的是$0~/pattern/
的后果 0 或 1
匹配胜利时返回 1, 失败返回 0.
举例
# 这边间接用于匹配没什么问题
awk 'BEGIN {if ("abc"~"^[a-z]+$") {print"match"} }'
#输入
match
awk 'BEGIN {if ("abc"~ /^[a-z]+$/) {print"match"} }'
#输入
match
# 这边将其赋值给其余变量, 此时其实 regex = $0 ~ /^[a-z]+$/, 也就是值 0
awk 'BEGIN {regex=/^[a-z]+$/; print regex; if ("abc"~ regex) {print"match"} }'
#输入
0
awk 'BEGIN {regex="^[a-z]+$"; print regex; if ("abc"~ regex) {print"match"} }'
#输入
^[a-z]+$
match
在 awk 中书写正则能够用 /[0-9]+/
也能够用
/[0-9]+/
匹配形式:”str” ~ /pattern/ 或 ”str” !~ /pattern/
匹配后果返回值为 0(匹配失败)或 1(匹配胜利)
任何独自呈现的 /pattern/ 都等价于 $0 ~ /pattern/
if(/pattern/)等价于 if($0 ~ /pattern/)
坑 1:a=/pattern/ 等价于将 $0 ~ /pattern/ 的匹配返回值(0 或 1)赋值给 a
坑 2:/pattern/ ~ $1 等价于 $0 ~ /pattern/ ~ $1,示意用 $1 去匹配 0 或 1
坑 3:/pattern/ 作为参数传给函数时,传递的是 $0~/pat/ 的后果 0 或 1
坑 4. 坑 5. 坑 6…
内置变量
awk 中能够看作是在一个独立的零碎空间中, 因而也有其非凡的零碎变量.
留神:
- 字段的援用不能加
$
, 这点与 Shell 不一样, 不然就变成获取记录中某个字段的值了.
管制 AWK 工作的预约义变量
-
FS
(field separator)输出数据的分隔符, 默认值是空格awk -F "," # 等价于 awk 'BEGIN {FS=","}' # 在读入文件之前设置字段分隔符
-
OFS
(output field separator)输入字段分隔符(默认是空格)awk 'BEGIN {OFS=","}'
FIELDWIDTHS
以指定宽度切割字段而非依照 FS-
FPAT
以正则匹配, 将匹配到的后果作为字段, 而非依照 FS 或 FIELDWIDTHS 划分. 了解为 re_match, 而不是 re_splitFPAT = "([^,]+)|(\"[^\"]+\")" # 上述 FPAT 用于宰割以逗号分隔的 csv 文件, 若应用双引号包裹的则视为是一个字段(疏忽其中的逗号). # 比方对于数据: abc,"pqr,mno" # $1 值为 abc # $2 值为 "pqr,mno"
https://stackoverflow.com/que…
-
RS
(record separator)记录宰割符(默认是\n
)该变量通常在 BEGIN 块中批改, 批改该变量能够管制 awk 每次读取的数据的范畴(默认是读取一行), 读取到的记录是不蕴含记录分隔符的.
- RS 设置为单个字符: 间接应用该字符来宰割记录
- RS 设置为多个字符: 视为正则(非兼容模式), 应用该正则来宰割记录.
awk 'BEGIN {RS=":"}' # 将记录宰割符设置为 : , 这样每次遇到 : 时就视为一条记录别离解决.
非凡读取需要
RS=""
: 按段落读取(这个个性有用)RS="\0"
: 一次性读取所有数据, 但有些非凡文件蕴含了空字符\0
RS="^$"
: 真正的一次性读取所有数据, 因而^$
匹配的是空文件RS="\n+"
: 按行读取, 但疏忽空行
-
ORS
(output row separator) 输入记录分隔符(默认是\n
)awk 'BEGIN {OFS=":"}'
CONVFMT
示意数据转换为字符串的格局, 默认值是%.6g
OFMT
示意数值输入的格局, 默认值是%0.6g
, 标识无效位 (整数局部加小数局部) 最多为 6.-
IGNORECASE
管制是否对大小写敏感, 当该变量设置时, 疏忽大小写. 在宰割记录时也受该变量影响.awk 'BEGIN{IGNORECASE=1} /amit/' marks.txt
携带信息的预约义变量
文件与行号
-
FILENAME
以后被解决的文件名在
BEGIN {}
块中, 该变量是未定义的. NR
(number of rows)记录的行号会始终累加, 就算解决多个文件, 该行号也会始终累加.
FNR
(file number of rows)记录的行号(解决不同文件时会重置)当解决多个文件时, 切换到不同文件则该值会重置掉.
-
NF
(number of fields)字段数量最初一个字段内容能够用 $NF 取出
-
ARGIND
用于解决多个文件时, 示意以后正在解决的文件的程序(从 1 开始)awk 'ARGIND==1 {if(FNR>3)print FNR,$3 } ARGIND==2 {if(FNR>1)print FNR,$2} ARGIND==3 {if(FNR<3)print FNR,$NF}' s.log t.log s.log
RT
(Record Termination) 理论记录宰割符当 RS 设置为多个字符 (正则) 时, 在每条记录被读取并宰割后,
RT
变量会被设置为理论用于划分记录的字符.
命令行与环境参数
ARGC
命令行地位参数个数(“ 选项 ” 是不蕴含在内的)-
ARGV
命令行地位参数数组ARGV[0]
值是命令名自身, 即awk
ARGV[1]
是传入的第 1 个参数- 范畴:
ARGV[0]
~ARGV[ARGC - 1]
-
ENVIRON
寄存零碎环境变量的关联数组awk 'BEGIN{print ENVIRON["USER"]}' # 输入: shell 变量 "USER"
-
PROCINFO
关联数组, 保留过程相干的信息# 打印 awk 过程的 Id awk 'BEGIN {print PROCINFO["pid"] }'
ERRNO
用于存储当 getline 重定向失败或 close 函数调用失败时的失败信息.
表达式
赋值操作符
-
=
=
的左右是能够有空格的.- 字符串拼接中的空格会被疏忽
Eg.
var = "hello" "world"
实际上 var 值是
"helloworld"
, 没有两头的空格 - 若是拼接两个字符串变量, 则应用字符串字面量隔开即可.
s3=s1""s2
++
反对前置递增和后置递增
--
反对前置递加增和后置递加
+=
-=
*=
/=
%=
^=
算数操作符
+
-
*
/
%
^
位操作
AND
按位与操作OR
按位或操作XOR
按位异或操作
关系操作符
<
>
<=
>=
==
留神, 判断两个值是否相等要用
==
, 而不是赋值运算符=
!=
~
字符匹配正则表达式!~
布尔操作符
&&
||
!
应用
!
时留神应用括号将相干表达式括起来, 防止写错.
三元运算符
condition expression ? statement1 : statement2
匹配运算符
除了块的条件匹配外, 还能够用于 if
判断之类的.
-
~
匹配指定正则表达式的, 用于主体块的条件匹配# 仅解决蕴含 hello 文本的行 awk '$0 ~"hello"' xx.txt # 留神这里正则是用 / / 包围起来, 而不是双引号 awk 'BEGIN {if ("[abc]"~ /\[.*\]/) {print"match";}}' #输入 #match # 留神这里用双引号括起来时, 外面用了双斜杠来解决正则的 [awk 'BEGIN { if ("[abc]"~"\\[abc\\]") {print"match";}}' #输入 #match
-
!~
不匹配指定正则表达式的, 用于主体块的条件匹配# 仅解决不含 hello 文本的行 awk '$0 !~"hello"' marks.txt
条件和循环
留神:
-
表达式后果: 0 为 false, 1 为 true
这个与 Shell 是相同的.
- 影响管制的语句:
break
,continue
综合示例
cat kpi.txt
user1 70 72 74 76 74 72
user2 80 82 84 82 80 78
#-------------- 计算每行数值的总之和平均值 -----------#
awk '{total=0; avg=0; for (i=2;i<=NF;i++) {total+=$i;} avg=total/(NF-1); print $1,total,avg;}' kpi.txt
user1 438 73
user2 486 81
if 条件语句
if (表达式) {} else if (表达式) {} else {}
执行多条语句要用
{}
, 只有一条语句时可疏忽.
for 循环
for (初始值; 循环判断条件; 累加) {}
while 循环
while (表达式) {}
do 循环
do {} while(表达式)
数组
一般数组
-
awk 的数组实际上是关联数组, 可通过下标 (数字实际上也是字符串) 顺次拜访
比方
arr[1]
和arr["1"]
实际上是对同一个 key 操作 -
反对多维数组
gawk(能够认为是 awk 的加强版, 代替版, 至多 centos 的 awk 理论就是 gawk) 反对真正意义上的多维数组.
awk 还有一种更 ” 原始 ” 的应用一维数组模仿多维数组的, 但在 gawk 中曾经没必要了.
# 定义
## 下标能够是数字 (视为字符串) 或字符串
数组名[下标] = 值
# 遍历
for (变量 in 数组名) {数组名[变量] # 获取对应数组值
}
# 删除数组
delete 数组
# 删除数组元素
delete 数组[下标]
# 判断数组中是否存在指定 "键"
if (key in array)
# 判断数组中是否不存在指定 "键", 留神这里额定加了一个括号, 不能省略了
if (!(key in array))
命令行参数数组
ARGC
命令行地位参数个数-
ARGV
命令行地位参数数组ARGV[0]
值是命令名自身, 即awk
ARGV[1]
是传入的第 1 个参数- 范畴:
ARGV[0]
~ARGV[ARGC - 1]
示例
cat argv.awk
内容
BEGIN {for (i=0; i<ARGC; i++) {print ARGV[i];
}
print ARGC;
}
# --------------------------------#
awk -f argv.awk afile 11 22 33
输入
awk # ARGV[0]
afile # ARGV[1]
11 # ARGV[2]
22 # ARGV[3]
33 # ARGV[4]
5 # ARGC
此处不会报错是因为 awk 脚本中只蕴含
BEGIN {}
局部, 因而不会将参数视为文件名并尝试关上.
数组函数
length(数组)
获取数组长度asort(数组 a[, 数组 b, ...])
对数组 a 的值进行排序,并且会丢掉原先键值(从新生成数字递增的 key 来代替), 并将后果赋予数组 b (若未传, 则间接批改数组 a).arorti(数组 a[, 数组 b, ...])
对数组 a 的键进行排序, 并将后果赋予数组 b (若未传, 则间接批改数组 a).
函数
算术函数
sin()
cos()
atan2(y,x)
exp(x)
返回自然数 e 的 x 次方sqrt()
平方根log(x)
计算 x 的自然对数int()
转换为整数(疏忽小数局部)-
rand()
伪随机数, 范畴[0,1)
, 默认应用srand(1)
初始化随机种子.若不应用
srand()
会发现每次获取的所谓随机数都是一样的.srand(); print rand();
srand([seed])
重置随机种子, 默认种子采纳以后工夫的 epoch 值(秒级别)
位操作函数
compl(num)
` 按位求补lshift(num, offset)
左移 N 位rshift(num, offset)
右移 N 位
字符串函数
awk 中波及字符索引的函数, 索引位都是从 1 开始.
留神, 不同 awk 版本, 函数参数个数是有可能不一样的.
sprintf(format, expr1, ...)
返回格式化后的字符串示例:
a = sprintf("%10s\n", "abc")
length(s)
返回字符串 / 数组的长度strtonum(str)
将字符串转换为十进制数值如果 str 以 0 结尾,则将其辨认为 8 进制
如果 str 以 0x 或 0X 结尾,则将其辨认为 16 进制
tolower(str)
转换为小写toupper(str)
转换为大写-
查找
index(str,substr)
在指标字符串中查找子串的地位, 若返回 0 则示意不存在.-
match(string, regexp, array)
字符串正则匹配, 将匹配后果保留在 arr 数组中.变量
RLENGTH
示意 match 函数匹配的字符串长度.变量
RSTART
示意 match 函数匹配的字符串的第一个字符的地位.awk 'BEGIN {if (match("One Two Three","re")) {print RLENGTH} }' # 输入 2 awk 'BEGIN {if (match("One Two Three","Thre")) {print RSTART} }' # 输入 9
cat test # this is wang,not wan # that is chen,not che # this is chen,and wang,not wan che awk '{match($0, /.+is([^,]+).+not(.+)/, a); print a[1],a[2]}' test # wang wan # chen che # chen wan che
-
替换
gsub(regx,sub [,targe=$0])
全局替换, 会间接批改原始字符串, 返回替换胜利的次数.如果
target
应用$0
,$...
等, 那么替换胜利后会应用 OFS 从新计算$0
这边
sub
不反对反向援用, 只能应用&
来援用匹配胜利的局部sub(regx,sub [,targe=$0])
只替换第一个匹配的, 会间接批改原始字符串, 返回替换胜利的次数.-
gensub(regx, sub [, how [, target]])
不批改原字符串, 而是返回替换后的字符串. 能够齐全代替gsub
和sub
how
: 指定替换第几个匹配, 比方 1 示意只替换第一个匹配,g
或G
示意全局替换这是 gawk 提供的函数, 其中
sub
反对应用\N
援用分组匹配, 或&
,\0
来标识匹配的整个后果.awk 'BEGIN { a = "111 222" b = gensub(/(.+) (.+)/, "\\2 \\1, \\0, &", "g", a) print b }' # 输入 222 111, 111 222, 111 222
-
截取
substr(str,pos,num= 残余所有)
从指定地位开始截取一个子串
-
宰割
split(str, arr [, 正则分隔符 =FS])
字符串宰割为数组, 并将其保留到第 2 个参数中, 函数返回值是宰割的数patsplit(str, arr[, 正则分隔符 =FPAT])
应用正则捕捉匹配的字符串, 并将其保留到第 2 个参数中.
若不分明的, 能够在 man awk
中搜寻相应关键字
工夫函数
systime
返回以后工夫戳(秒级)-
mktime("YYYY MM DD HH mm SS [DST]")
依据给定的字符串格局, 返回其对应的工夫戳# 格局: 年 月 日 时 分 秒 awk 'BEGIN{print mktime("2020 10 10 17 51 59")}'
-
strftime([format [, timestamp[, utc-flag]]])
将工夫戳 (默认是以后工夫) 转换为字符串示意awk 'BEGIN {print strftime("Time = %Y-%m-%d %H:%M:%S")}' 输入 Time = 2020-10-12 17:53:37
SN 形容 %a 星期缩写(Mon-Sun)。 %A 星期全称(Monday-Sunday)。 %b 月份缩写(Jan)。 %B 月份全称(January)。 %c 本地日期与工夫。 %C 年份中的世纪局部,其值为年份整除 100。 %d 十进制日期(01-31) %D 等价于 %m/%d/%y. %e 日期,如果只有一位数字则用空格补齐 %F 等价于 %Y-%m-%d,这也是 ISO 8601 规范日期格局。 %g ISO8610 规范周所在的年份模除 100(00-99)。比方,1993 年 1 月 1 日属于 1992 年的第 53 周。所以,尽管它是 1993 年第 1 天,然而其 ISO8601 规范周所在年份却是 1992。同样,只管 1973 年 12 月 31 日属于 1973 年然而它却属于 1994 年的第一周。所以 1973 年 12 月 31 日的 ISO8610 规范周所在的年是 1974 而不是 1973。 %G ISO 规范周所在年份的全称。 %h 等价于 %b. %H 用十进制示意的 24 小时格局的小时(00-23) %I 用十进制示意的 12 小时格局的小时(00-12) %j 一年中的第几天(001-366) %m 月份(01-12) %M 分钟数(00-59) %n 换行符 (ASCII LF) %p 十二进制表示法(AM/PM) %r 十二进制表示法的工夫(等价于 %I:%M:%S %p)。 %R 等价于 %H:%M。 %S 工夫的秒数值(00-60) %t 制表符 (tab) %T 等价于 %H:%M:%S。 %u 以数字示意的星期(1-7),1 示意星期一。 %U 一年中的第几个星期(第一个星期天作为第一周的开始),00-53 %V 一年中的第几个星期(第一个星期一作为第一周的开始),01-53。 %w 以数字示意的星期(0-6),0 示意星期日。 %W 十进制示意的一年中的第几个星期(第一个星期一作为第一周的开始),00-53。 %x 本地日期示意 %X 本地工夫示意 %y 年份模除 100。 %Y 十进制示意的残缺年份。 %z 时区,示意格局为 +HHMM(例如,格局要求生成的 RFC 822 或者 RFC 1036 工夫头) %Z 时区名称或缩写,如果时区待定则无输入。
其余函数
getline
请参照下方的 “getline” 局部.
close(xxx [, from|to])
敞开文件、shell 过程, 能够仅敞开某一端.
close(xxx, "to")
示意敞开该管道的写入端,close(xxx, "from")
示意敞开该管道的输入端.留神!!!! awk 中任何文件都只会在第一次应用时关上, 之后都不会再从新关上(而是从上次的读取地位持续). 因而只有在敞开之后, 再次应用时才会从新关上.
next
跳过对以后记录的后续解决.会回到 awk 循环的头部, 读取下一行.
nextfile
进行解决以后文件, 从下一个文件开始解决.return xx
函数返回值system("shell 命令")
执行 shell 命令, 并返回退出的状态值, 0 示意胜利.flush([output-expr])
刷新关上文件或管道的缓冲区如果没有提供 output-expr,fflush 将刷新规范输入。若 output-epxr 是空字符串 (“”),fflush 将刷新所有关上的文件和管道。
-
close(expr)
敞开文件句柄 ???awk 'BEGIN {cmd = "tr [a-z] [A-Z]" print "hello, world !!!" |& cmd # "&|" 示意双向管道通信 close(cmd, "to") # 敞开其中一个方向的管道, 另一个是 "from" 方向 cmd |& getline out # 应用 getline 函数将输入存储到 out 变量中 print out; close(cmd); # 敞开管道 }' 输入 HELLO, WORLD !!!
exit <code=0>
终止脚本
自定义函数
function 函数名(参数) {
awk 语句
return awk 变量
}
留神
- 自定义函数的书写不能再
BEGIN{}
,{}
,END{}
的里层
getline
getline 函数用于读取一行数据.
依据不同状况, 返回值不一样.
- 若读取到数据, 返回 1.
- 若遇到 EOF, 返回 0.
- 产生谬误, 返回正数. 如 - 1 示意文件无奈关上,- 2 示意 IO 操作须要重试(retry)。在遇到谬误的同时,还会设置 ERRNO 变量来形容谬误.
awk '{print $0; getline; print $0}' marks.txt
# 倡议应用 getline 时判断一下是否读取胜利
awk 'BEGIN {getline; if ((getline) > 0) {...}}'
从以后文件读取
- 应用
getline
不带参数时, 示意从以后正在解决的文件中立刻读取下一条记录并保留到$0
, 同时进行字段宰割(别离存到$1
,$2
,…), 同时会设置 NF, RT, NR, FNR, 而后继续执行后续代码. - 执行
getline < 变量名 >
时, 会将读取后果保留到对应变量中, 而不会更新$0
, 也不会更新 NF,$1
,$2
, …, 此时仅仅会更新 RT, NR, FNR.
从其余文件读取
-
执行
getline < "filename"
示意从指定文件读取一条记录并保留到$0
中(同时进行字段宰割), 及 NF. 至于 NR, FNR 则不会更新.每次读取记录后会自动记录读取的地位.
配合
while
及getline
的返回值能够遍历完文件.留神
getline < abc
与getline < "abc"
是两码事, 一个是从 abc 变量指向的文件读取, 一个是读取 abc 文件 - 执行
getline 变量名 < "filename"
示意从指定文件读取一条记录并保留到指定变量中.
从 shell 命令输入后果中读取
cmd | getline
:从 Shell 命令cmd
的输入后果中读取一条记录保留到$0
中会进行字段划分,设置变量
$0
NF
$N
RT
,不会批改变量NR
FNR
cmd | getline var
: 从 Shell 命令cmd
的输入后果中读取数据保留到var
中除了
var
和RT
,其它变量都不会设置
如果要再次执行 cmd 并读取其输入数据,则须要 close 敞开该命令, 示例:。
# 若屏蔽下方的 close 函数, 则再次读取该 cmd 时为空. 因而须要敞开先.
awk 'BEGIN {cmd ="seq 1 5"; \
while((cmd | getline) > 0) {print}; \
close(cmd); \
while((cmd | getline) > 0) {print}; \
}'
能够不便地应用 shell 给 awk 中变量赋值
awk 'BEGIN {get_date ="date +\"%F %T\""; \
get_date | getline cur_date; \
print cur_date; \
close(get_date);
}'
输入
2020-10-13 19:14:17
将数据传给 shell 解决完(coprocess), 再读取
这里要利用 coprocess, 也就是 |&
操作符.
awk 能够利用 |&
将一些不好解决的数据传给 shell 来解决后, 再从 shell 中读取后果, 持续在 awk 中解决.
应用 shell 的排序功能
# sort 命令会期待数据写入结束后 (即 EOF 标记) 才开始排序, 因而理论是在执行 close(CMD, "to") 时才开始执行.
awk 'BEGIN {
CMD = "sort -k2n";
print "6 66" |& CMD;
print "3 33" |& CMD;
print "7 77" |& CMD;
close(CMD, "to");
while ((CMD |& getline) > 0) {print;}
close(CMD);
}'
输入:
3 33
6 66
7 77
应用留神:
awk-print |& cmd
会间接将数据写进管道, cmd 能够从管道中获取数据- 强烈建议在 awk_print 写完数据之后加上
close(cmd,"to")
,这样示意向管道中写入一个 EOF 标记,防止某些要求读完所有数据再执行的 cmd 命令被永恒阻塞.敞开管道另一端能够应用
close(cmd, "from")
- 如果
cmd
是按块缓冲的,则getline
可能会陷入阻塞。这时可将cmd
局部改写成stdbuf -oL cmd
以强制其按行缓冲输入数据CMD="stdbuf -oL cmdline";awk_print |& CMD;close(CMD,"to");CMD |& getline
高级输入
print 输入重定向
print "..."
print "..." > 文件名
重定向输入-
print "..." >> 文件名
重定向输入这玩意比应用
system
函数再调用 echo 快了好几个量级 print "..." | "shell 命令"
awk 将创立管道, 并启动 shell 命令. print 产生的数据放入管道, shell 命令则从管道中读取数据.print "..." |& "shell 命令"; "shell 命令" | getline
和下面的|
不同之处在于, 这里是将数据交给 Coprocess, 之后 awk 还须要再从 Coprocess 取回数据.Coprocess 执行 shell 命令的时候, 后果是不输入到规范输入的, 而是须要从管道中自行读取.
反对重定向到
- 规范输出
/dev/stdin
- 规范输入
/dev/stdout
- 规范谬误
/dev/stderr
若 print 输入后发现后续的管道命令没有内容, 那其实是因为 awk 的输入存在缓存, 可应用 fflush()
函数刷新缓冲区.
对于 |
和 |&
应用上区别的示例
# 这里用的是 |, 执行后果间接输入到规范输入
awk 'BEGIN {cmd = "tr \"[a-z]\"\"[A-Z]\""print"hello" | cmd
> }'
# 这里用的是 |&, 执行后果须要手动从 Coprocess 管道读取
awk 'BEGIN {cmd = "tr \"[a-z]\"\"[A-Z]\""print"hello" |& cmd;
close(cmd, "to");
cmd |& getline line;
print line;
close(cmd);
}'
输入
HELLO
printf 格式化
printf(format, value1, value2, ...)
参数
format 格局
%c (将 ASCII 转换为)字符
%s 字符串
%d,%i 整数
%e,$e 迷信计数法示意
%f,%F 浮点数
%g,%G 浮点数, 会移除对数值无影响的 0
%o 无符号八进制
%u 无符号十进制
%x,%X 无符号十六进制
%% 百分号
留神: 输入时不会主动换行
示例
printf("total pay for %s is $%.2f\n", $1, $2 * $3)
# %-8s 字符串, 8 个字符宽度, 左对齐
# %6.2f 浮点数, 6 个字符宽度, 保留 2 位小数
printf("%-8s %6.2f\n", $1, $2 * $3)
参考: https://awk.readthedocs.io/en…
若仅仅是为了格式化字符串(不输入), 能够用 sprintf 函数.
format 反对的转义序列
- 换行符
\n
- 程度制表符
\t
-
垂直制表符
\v
了解为输入光标垂直向下挪动一行
-
退格符
\b
了解为输入光标后退一格.
-
回车符
\r
了解为光标会回退到以后行的结尾(罕用于笼罩本行)
-
换页符
\f
这个成果 … 得试一下才行
format 的 %
的可选参数
-
宽度
只有当字段的宽度比要求宽度小时该标示才会无效, 默认应用空格字符填充.
printf("%10d", 1) 输入 1
-
前导零
0
只有当字段的宽度比要求宽度小时该标示才会无效
awk 'BEGIN {printf("%010d", 1)}' 输入 0000000001
-
左对齐
-
在
%
和数字之间应用-
符号即可指定左对齐awk 'BEGIN {printf("%-10d", 1)}' 输入 1
-
符号前缀
+
应用
+
, 在输入数字时, 将其正负号也输入.awk 'BEGIN {printf("%+10d", 1)}' 输入 +1
-
保留进制标识
#
awk 'BEGIN {printf("%#o %#X\n", 10, 10)}' 输入 012 0XA
Examples
打印出以后的可用内核列表
并显示序号
awk -F "'"'/^menuentry/ {print x++,$2}' /boot/grub2/grub.cfg
输入
0 CentOS Linux (5.5.6) 7 (Core)
1 CentOS Linux (3.10.0-1062.12.1.el7.x86_64) 7 (Core)
2 CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)
3 CentOS Linux (0-rescue-d64aa77b8f014365aa6557986697df9c) 7 (Core)
统计以后 tcp 的各个状态及数量
netstat -ntp | awk '/^tcp / {S[$6]++} END{for (i in S) print i,S[i];}'
输入
TIME_WAIT 108
ESTABLISHED 154
统计每个接口的拜访工夫
time cat 20_10_*.txt | grep "request cost" | gawk -v suffix=_test -f ../stat_method.awk
stat_method.awk
BEGIN {
DEBUG = 1
methodRecordFile = "method_record"suffix".csv"
methodStatsFile = "method_stats"suffix".csv"
if (DEBUG) {
methodRecordFile = "/dev/stdout"
methodStatsFile = "/dev/stdout"
}
print methodRecordFile
print methodStatsFile
}
{method=substr($10,2,length($10)-2)
method=substr(method,1,length(method)-7)
timeStr=$1" "$2
timeMs=$6 + 0.01
uid=substr($11,2,length($11)-2)
msLevel=(int(timeMs/100) + 1) * 100
T[method][msLevel]++
if (!(method in Stats)) {Stats[method]["name"] = method
Stats[method]["max"] = 0
Stats[method]["mean"] = 0
Stats[method]["count"] = 0
Stats[method]["sum"] = 0
Stats[method]["sumX2"] = 0
Stats[method]["min"] = 9999999999999
}
if (timeMs > Stats[method]["max"]) {Stats[method]["max"] = timeMs
}
if (timeMs < Stats[method]["min"]) {Stats[method]["min"] = timeMs
}
Stats[method]["sumX2"] += timeMs * timeMs
Stats[method]["count"]++
Stats[method]["sum"] += timeMs
if (NR % 10000 == 0) {print "已解决"NR"条记录"}
}
END {
print "----------- 总共解决"NR"条记录 -----------"
print "method,msLevel,count" > methodRecordFile
# print "method,msLevel,count"
for (m in T) {for (l in T[m]) {print m","l","T[m][l] >> methodRecordFile
# print m","l","T[m][l]
}
}
print "----------- done -----------"
print "method,min,max,mean,sd(标准差),count,sum(秒)" > methodStatsFile
printf("%-30s\tmin\tmax\tcount\tmean\tsd(标准差)\t,sum(秒)\n", "method")
for (m in Stats) {Stats[m]["mean"] = Stats[m]["sum"] / Stats[m]["count"]
Stats[m]["sd"] = sqrt(Stats[m]["sumX2"] / Stats[m]["count"] - Stats[m]["mean"] * Stats[m]["mean"])
# for (n in Stats[m]) {# print "Stats["m"]["n"]=" Stats[m][n]
# }
print m "," Stats[m]["min"] "," Stats[m]["max"] "," Stats[m]["mean"] "," Stats[m]["sd"]"," Stats[m]["count"]","Stats[m]["sum"]/1000 >> methodStatsFile
printf("%-30s\t%.2f\t%.2f\t%.0f\t%.2f\t%d\t%.2f\n", substr(m, 0, 30), Stats[m]["min"], Stats[m]["max"],Stats[m]["mean"],Stats[m]["sd"], Stats[m]["count"], Stats[m]["sum"]/1000)
}
print "----------- done -----------"
print methodRecordFile
print methodStatsFile
}
格式化空白
cat > a.txt <<'EOF'
aaaa bbb ccc
bbb aaa ccc
ddd fff eee gg hh ii jj
EOF
awk 'BEGIN{OFS=" "} {NF=NF; print}' a.txt
输入
aaaa bbb ccc
bbb aaa ccc
ddd fff eee gg hh ii jj
打印 ini 文件中的某一段
awk -v scope="extras" 'BEGIN {scope="["scope"]"}
$0 == scope {
print;
while ((getline) > 0) {if ($0 !~ /\[.*\]/) {print $0;} else {exit}
}
}
' /etc/yum.repos.d/CentOS-Base.repo
输入如下 ????
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
#additional packages that extend functionality of existing packages
解决字段中蕴含字段宰割符状况(csv)
echo 'Robbins,Arnold,"1234 A Pretty Street, NE","MyTown",MyState,12345-6789,USA' | awk 'BEGIN {FPAT="[^,]+|\"[^\"]+\""} {print NF" "$3}'
输入如下 ????
7 "1234 A Pretty Street, NE"