https://www.cnblogs.com/codelogs/p/16060082.html

简介#

刚开始入门awk时,觉得awk很简单,像是一个玩具,根本无法应用到工作之中,但随着对awk的了解不断加深,就会越发觉得这玩意的强大,大佬们称其为上古神器,绝不是空穴来风。
这也可以说明,一些热门的技术知识点,如果你觉得它不过如此,那绝对是你对它的掌握不够深入,而不是它没啥用。

基本语法#

awk基本语法如下:

awk 'BEGIN{//your code} pattern1{//your code} pattern2{//your code} END{//your code}'
  1. BEGIN部分的代码,最先执行
  2. 然后循环从管道中读取的每行文本,如果匹配pattern1,则执行pattern1的代码,匹配pattern2,则执行pattern2中的代码
  3. 最后,执行END部分的代码
    如下所示,分别求奇数行与偶数行的和:
$ seq 1 5
1
2
3
4
5 $ seq 1 5|awk 'BEGIN{print "odd","even"} NR%2==1{odd+=$0} NR%2==0{even+=$0} END{print odd,even}'
odd even
9 6
  1. seq 1 5用来生成1到5的数字。
  2. awk先执行BEGIN块,打印标题。
  3. 然后第1行尝试匹配NR%2==1这个pattern,其中NR为awk的内置变量,表示行号,$0为awk读到的当前行数据,显然匹配NR%2==1,则执行里面的代码。
  4. 然后第1行尝试匹配NR%2==0这个pattern,显然不匹配。
  5. 然后第2行、第3行...,一直到最后一行,都执行上面两步。
  6. 最后执行END块,将前面求和的变量打印出来,其中9=1+3+56=2+4
    这个程序还可以如下这样写:
seq 1 5|awk 'BEGIN{print "odd","even"} {if(NR%2==1){odd+=$0}else{even+=$0}} END{print odd,even}'

这里使用了if语句,实际上awk的程序语法与C是非常类似的,所以awk也有else,while,for,break,continue,exit

另外,可以看到,awk程序在处理时,默认是一行一行处理的,注意我这里说的是默认,并不代表awk只能一行一行处理数据,接下来看看awk的分列功能,可通过-F选项提供,如下:

$ paste <(seq 1 5) <(seq 6 10) -d,
1,6
2,7
3,8
4,9
5,10 $ paste <(seq 1 5) <(seq 6 10) -d, |awk -F, '{printf "%s\t%s\n",$1,$2}'
1 6
2 7
3 8
4 9
5 10

这个例子用-F指定了,,这样awk会自动将读取到的每行,使用,分列,拆分后的结果保存在$1,$2...中,另外,你也可以使用$NF,$(NF-1)来引用最后两列的值,不指定-F时,awk默认使用空白字符分列。
注意这里面的printf "%s\t%s\n",$1,$2,printf是一个格式化打印函数,其实也可以写成printf("%s\t%s\n", $1, $2),只不过awk中函数调用可以省略括号。

上面已经提到了NR这个内置变量,awk还有如下内置变量

内置变量 作用
FS 与-F功能类似,用来分列的,不过FS可以是正则表达式,默认是空白字符
OFS 与FS对应,指定print函数输出时的列分隔符,默认空格
RS 记录分隔符,默认记录分隔符是\n
ORS 与RS对应,指定print函数输出时的记录分隔符,默认\n

用2个例子体会一下:

$ echo -n '1,2,3|4,5,6|7,8,9'|awk 'BEGIN{RS="|";FS=","} {print $1,$2,$3}'
1 2 3
4 5 6
7 8 9
$ echo -n '1,2,3|4,5,6|7,8,9'|awk 'BEGIN{RS="|";FS=",";ORS=",";OFS="|"} {print $1,$2,$3}'
1|2|3,4|5|6,7|8|9,

总结:awk数据读取模式,总是以RS为记录分隔符,一条一条记录的读取,然后每条记录按FS拆分为字段。

再看看这个例子:

$ seq 1 5|awk '/^[1-4]/ && !/^[3-4]/'
1
2
$ seq 1 5|awk '$0 ~ /^[1-4]/ && $0 !~ /^[3-4]/{print}'
1
2
$ seq 1 5|awk '$0 ~ /^[1-4]/ && $0 !~ /^[3-4]/{print $0}'
1
2

可以看到:

  1. awk中pattern部分可以直接使用正则表达式,而且可以使用&&,||,!这样的逻辑运算符.
  2. 如果正则表达式没有指定匹配变量,默认对$0执行匹配,所以awk '/regex/'直接就可以等效于grep -E 'regex'.
  3. 另外pattern后面的代码部分如果省略的话,默认打印$0.
  4. print函数如果没有指定参数,也默认打印$0.
  5. 另外,一定注意awk中的正则表达式不支持\d,匹配数字请使用[0-9],因为linux中正则语法分BRE,ERE,PCRE,而awk支持的是ERE.

到这里,awk基本语法就差不多讲完了,接下来会介绍一些常用的场景。

查找与提取#

示例数据如下,也是用awk生成的:

$ seq 1 10|awk '{printf "id=%s,name=person%s,age=%d,sex=%d\n",$0,$0,$0/3+15,$0/6}'|tee person.txt
id=1,name=person1,age=15,sex=0
id=2,name=person2,age=15,sex=0
id=3,name=person3,age=16,sex=0
id=4,name=person4,age=16,sex=0
id=5,name=person5,age=16,sex=0
id=6,name=person6,age=17,sex=1
id=7,name=person7,age=17,sex=1
id=8,name=person8,age=17,sex=1
id=9,name=person9,age=18,sex=1
id=10,name=person10,age=18,sex=1

然后用awk模拟select id,name,age from person where age > 15 and age < 18 limit 4这样SQL的逻辑,如下:

$ cat person.txt |awk 'match($0, /^id=(\w+),name=(\w+),age=(\w+)/, a) && a[3]>15 && a[3]<18 { print a[1],a[2],a[3]; if(++limit >= 4) exit 0}'
3 person3 16
4 person4 16
5 person5 16
6 person6 17
  1. 首先使用match函数以及正则表达式的捕获组功能,将id,name,age的值提取到a[1],a[2],a[3]中.
  2. 然后a[3]>15 && a[3]<18即类似SQL中age > 15 and age < 18的功能.
  3. 然后打印a[1],a[2],a[3],类似SQL中select id,name,age的功能.
  4. 最后,如果打印条数到达4条,退出程序,即类似limit 4的功能.

简单统计分析#

awk可以做一些简单的统计分析任务,还是以SQL为例。
select age,sex,count(*) num, group_concat(id) ids from person where age > 15 and age < 18 group by age,sex这样的统计SQL,用awk实现如下:

$ cat person.txt |awk '
BEGIN{
printf "age\tsex\tnum\tids\n"
}
match($0, /^id=(\w+),name=(\w+),age=(\w+),sex=(\w+)/, a) && a[3]>15 && a[3]<18 {
s[a[3],a[4]]["num"]++;
s[a[3],a[4]]["ids"] = (s[a[3],a[4]]["ids"] ? s[a[3],a[4]]["ids"] "," a[1] : a[1])
}
END{
for(key in s){
split(key, k, SUBSEP);
age=k[1];
sex=k[2];
printf "%s\t%s\t%s\t%s\n",age,sex,s[age,sex]["num"],s[age,sex]["ids"]
}
}'
age sex num ids
17 1 3 6,7,8
16 0 3 3,4,5

awk代码稍微有点长了,但逻辑还是很清晰的。

  1. BEGIN中打印标题行.
  2. match获取出id,name,age,sex,并过滤age>15且age<18的数据,然后将统计结果累计到s这个关联数组中。你可以把s这个关联数组想象中map,然后只是有两级key而已。(注意在awk中,拼接字符串使用空格即可,并不像java中使用+号).
  3. 最后END块中,遍历s这个关联数组,注意,类似s[a[3],a[4]]这样,在awk中是一个key,awk会使用SUBSEP这个变量将a[3],a[4]拼接起来,需要split(key, k, SUBSEP),将key按SUBSEP拆分到k中,SUBSEP默认是\034文件分隔符.

处理csv#

csv是以一行为一条记录,以,号分隔为列的数据格式,awk天然适合处理csv这样的数据,但在列值中本身存在,号时,只使用-F就不行了,这时可以使用FPAT,如下:

$ echo 'aa,"bb,cc",dd'|gawk 'BEGIN { FPAT = "[^,]+|\"[^\"]+\"" } { print $3 }'
dd

FPAT变量用于提取字段值,这里指定为正则表达式,只不过这个正则表达式可以匹配类似aa"bb,cc"这种数据.

按段拆分记录#

awk可以按段拆分记录,什么是段呢,看一下ifconfig的输出,如下:

$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.73.125 netmask 255.255.240.0 broadcast 172.17.79.255
inet6 fe80::215:5dff:fe4c:c155 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:4c:c1:55 txqueuelen 1000 (Ethernet)
RX packets 35008 bytes 5829277 (5.8 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4435 bytes 7152614 (7.1 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 82 bytes 4100 (4.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 82 bytes 4100 (4.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ifconfig的输出中,eth0与lo的数据使用空行间隔开了,像这种,用空行间隔的内容,其中eth0部分是一个段,lo部分也是一个段,而在awk中,RS=""即表示按段拆分记录,所以获取eth0网卡ip地址的方法是:

$ ifconfig|awk -v RS="" '/^eth0/{print $6}'
172.17.73.125

这里用-v RS=""来设置RS变量,与在BEGIN中效果是一样的,-v name=var是shell向awk内部传递变量的一种方法。

另外,java中jstack获取的线程栈的内容,也是以空行分段输出的,用awk来处理也很简单,比如,我们只看目前与mysql有关的线程栈,如下:

$ jstack `pgrep java`|awk -v RS="" '/mysql/'
"Abandoned connection cleanup thread" #18 daemon prio=5 os_prio=0 tid=0x00007fbb893d0000 nid=0xd75 in Object.wait() [0x00007fbb586ad000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000e160ee38> (a java.lang.ref.ReferenceQueue$Lock)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:40)

到这里,我们不难想到,用awk来搜索异常日志,其实比grep更方便,比如java中如下的错误日志:

$ cat app_demo.log
[2020-12-23 20:12:51] [app_demo] [172.29.128.1] [INFO] [RMI TCP Connection(7)-172.29.128.1] {"logger":"o.a.catalina.core.ContainerBase.[Tomcat].[localhost].[/]","msg":"Initializing Spring DispatcherServlet 'dispatcherServlet'"}
[2020-12-23 20:12:51] [app_demo] [172.29.128.1] [INFO] [RMI TCP Connection(7)-172.29.128.1] {"logger":"org.springframework.web.servlet.DispatcherServlet","msg":"Initializing Servlet 'dispatcherServlet'"}
[2020-12-23 20:12:51] [app_demo] [172.29.128.1] [INFO] [RMI TCP Connection(7)-172.29.128.1] {"logger":"org.springframework.web.servlet.DispatcherServlet","msg":"Completed initialization in 26 ms"}
[2020-12-23 20:15:00] [app_demo] [172.29.128.1] [ERROR] [redisson-netty-1-6] {"logger":"org.redisson.client.handler.CommandsQueue","msg":"Exception occured. Channel: [id: 0x43577278, L:/127.0.0.1:61888 - R:localhost/127.0.0.1:22122]
java.io.IOException: 远程主机强迫关闭了一个现有的连接。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:347)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)"} # 使用grep直接搜索IOException,效果如下,看不到前后的调用栈了
$ cat app_demo.log |grep 'IOException'
java.io.IOException: 远程主机强迫关闭了一个现有的连接。 # grep可以使用-B -C指定匹配内容前面显示几行,后面显示几行,如grep -B 2 -C 10
# 效果如下,由于不知道线程栈有多深,-C有时会设置小了,有时又会设置大了
$ cat app_demo.log |grep -B2 -C10 'IOException'
[2020-12-23 20:12:51] [app_demo] [172.29.128.1] [INFO] [RMI TCP Connection(7)-172.29.128.1] {"logger":"org.springframework.web.servlet.DispatcherServlet","msg":"Completed initialization in 26 ms"}
[2020-12-23 20:15:00] [app_demo] [172.29.128.1] [ERROR] [redisson-netty-1-6] {"logger":"org.redisson.client.handler.CommandsQueue","msg":"Exception occured. Channel: [id: 0x43577278, L:/127.0.0.1:61888 - R:localhost/127.0.0.1:22122]
java.io.IOException: 远程主机强迫关闭了一个现有的连接。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:347)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)" # 使用awk,RS='\n\\S',效果如下,简直完美!
$ cat app_demo.log |awk -v RS='\n\\S' '/IOException/'
2020-12-23 20:15:00] [app_demo] [172.29.128.1] [ERROR] [redisson-netty-1-6] {"logger":"org.redisson.client.handler.CommandsQueue","msg":"Exception occured. Channel: [id: 0x43577278, L:/127.0.0.1:61888 - R:localhost/127.0.0.1:22122]
java.io.IOException: 远程主机强迫关闭了一个现有的连接。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:347)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)"}

这里的RS='\n\\S'是一个正则表达式,记录分隔符为换行符后面带一个非空白符。

最后,指定RS='^$'可以将数据一次性的读取到$0中,这也是一个常用的小技巧,因为^$显然无法匹配任何字符,这样awk就会将所有数据读取到一条记录中了。
如下,将多行数据用,拼接为一行数据:

$ seq 1 10|awk -v RS='^$' '{gsub(/\n/, "," , $0);print $0}'
1,2,3,4,5,6,7,8,9,10,

范围匹配#

awk中另一个比grep强的地方,就是awk可以使用范围过滤数据,而grep只能使用正则,比如我们要搜索2021-01-04 23:33:402021-01-04 23:34:16的日志:

# 搜索2021-01-04 23:33:40到2021-01-04 23:34:16的日志,前提是这两个时间在日志中都存在,因为awk是在遇到2021-01-04 23:33:40后,开启打印,直到遇到2021-01-04 23:34:16又关闭打印
cat app.log|awk '/2021-01-04 23:33:40/,/2021-01-04 23:34:16/' # 另一种更有效的方式
cat app.log|awk 'match($0,/^\[([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})\]/,a){
if(a[1]>="2021-01-07 12:26:43")
print $0;
if(a[1]>"2021-01-07 12:26:56") exit
}'

多文件join处理#

awk还可以实现类似SQL中的join处理,求交集或差集,如下:

$ cat user.txt
1 zhangsan
2 lisi
3 wangwu
4 pangliu $ cat score.txt
1 86
2 57
3 92 # 类似 select a.id,a.name,b.score from user a left join score b on a.id=b.id
# 这里FNR是当前文件中的行号,而NR一直是递增的,所以对于第一个score.txt,NR==FNR成立,第二个user.txt,NR!=FNR成立
$ awk 'NR==FNR{s[$1]=$2} NR!=FNR{print $1,$2,s[$1]}' score.txt user.txt
1 zhangsan 86
2 lisi 57
3 wangwu 92
4 pangliu # 当然,也可以直接使用FILENAME内置变量,如下
$ awk 'FILENAME=="score.txt"{s[$1]=$2} FILENAME=="user.txt"{print $1,$2,s[$1]}' score.txt user.txt # 求差集,打印user.txt不在score.txt中的行
$ awk 'FILENAME=="score.txt"{s[$1]=$2} FILENAME=="user.txt" && !($1 in s){print $0}' score.txt user.txt
4 pangliu

awk常用函数#

函数名 说明 示例
sub 替换一次 sub(/,/,"|",$0)
gsub 替换所有 gsub(/,/,"|",$0)
match 匹配,捕获内容在a数组中 match($0,/id=(\w+)/,a)
split 拆分,拆分内容在a数组中 split($0,a,/,/)
index 查找字符串,返回查找到的位置,从1开始 i=index($0,"hi")
substr 截取子串 substr($0,1,i)substr($0,i)
tolower 转小写 tolower($0)
toupper 转大写 toupper($0)
srand,rand 生成随机数 BEGIN{srand();printf "%d",rand()*10}

替换其它文本处理命令#

grep

命令 说明 awk实现
grep 'regex' 过滤记录 awk '/regex/'

sed

命令 说明 awk实现
sed -n '/regex/ p' 过滤记录 awk '/regex/'
sed -n '1,5 p' 显示前5行 awk 'NR<=5'
sed '/1~2/ s/hello/hi/g' 奇数行所有hello替换为hi awk 'NR%2==1{gsub(/hello/,"hi",$0);print $0}'
sed '/regex/ d' 删除匹配行 awk '!/regex/'
sed '1 i\id,name' 第1行插入一行标题 awk '{if(NR==1) print "id,name"; print $0}'
sed '1 a\id,name' 第1行后面添加一行 awk '{print $0; if(NR==1) print "id,name"}'
sed '1 c\id,name' 修改第1行整行内容 awk '{if(NR==1){print "id,name"}else{print $0}}'

可以发现,sed其实是awk程序在某些场景的固化,因为awk程序类似awk 'pattern{}',而sed程序类似sed 'pattern action',action就是p,s,d,i,a,c这些动作,而这些动作对应awk固化在{}中的代码。

然后grep是进一步的场景固化,它只支持正则过滤。

tr

命令 说明 awk实现
tr -d '\n' 删除换行符 awk -v RS='^$' '{gsub(/\n/, "" , $0);print $0}'
tr -s ' ' 压缩多个空格为一个,awk的这个实现有点hack awk '{$1=$1;print $0}'
tr [a-z] [A-Z] 转大写 awk '{print toupper($0)}'

cut

命令 说明 awk实现
cut -d, -f2 ,拆分取第2个字段 awk -F, '{print $2}'

head

命令 说明 awk实现
head -n10 取前10行 awk '{print $0;if(++n >= 10) exit 0}'

tail

命令 说明 awk实现
tail -n10 取倒数10行 这个直接用awk实现有点长,没必要,可以用tac辅助
`tac test.log

wc

命令 说明 awk实现
wc -l 统计文件行数 awk 'END{print NR}'

uniq

命令 说明 awk实现
uniq -c 分组计数 awk '{s[$0]++} END{for(k in s){print s[k],k}}'

总结#

awk其本身就是为文本处理而生的,不太复杂的临时性的文本处理分析,第一个想到的就应该是它!
后面,我再总结一下shell本文处理的常见技巧,作为本篇的补充。

往期内容#

不容易自己琢磨出来的正则表达式用法
好用的parallel命令
还在胡乱设置连接空闲时间?
常用网络命令总结
使用socat批量操作多台机器

[转帖] 原来awk真是神器啊的更多相关文章

  1. 在Mac上快速Kill掉Tomcat

    最近IDEA总是会莫名其妙的挂掉,而挂掉之后通过IDEA开启的Tomcat却没有同步给关掉,等我再在IDEA里要启动的时候,就不行了.... 这时,就需要手动去kill掉tomcat,每次先 ps - ...

  2. 精通shell编程--最后的总结

    不得不说shell语法是丑陋的,操作是简单高效的,最后一次学习总结shell shell总结 字符串删除与替换等常见操作 ## 字符串长度 a=1234 echo "${#a}" ...

  3. 常见的Socket网络异常场景分析

    原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 在目前微服务的背景下,网络异常越来越常见了,而有一些网络异常非常模糊,理解什么情况下会导致什么异常,还是有一定难度 ...

  4. awk神器

      序   产品经理(PM)过来找你要最近某某的数据,而你知道这些数据目前只能通过日志文件去分析,因为我们知道,我们不可能把所有数据都放入db中(这不科学啊!).每当有这样任务的时候,你就用php或j ...

  5. 【转帖】Linux命令行操作json神器jq

    Linux命令行操作json神器jq https://www.cnblogs.com/chenqionghe/p/11736942.html jq类似一个awk或grep一样的神器,可以方便地在命令行 ...

  6. [转帖]awk 入门

    awk其实不仅仅是工具软件,还是一种编程语言.不过,本文只介绍它的命令行用法,对于大多数场合,应该足够用了. http://www.ruanyifeng.com/blog/2018/11/awk.ht ...

  7. [转帖]linux下网络监控神器"iptraf-ng"

    linux下网络监控神器"iptraf-ng" https://www.cnblogs.com/dupengfei/articles/iptraf-ng.html 优点:监控的网络 ...

  8. 【转帖】vim/sed/awk/grep等文件批处理总结

    vim/sed/awk/grep等文件批处理总结 https://www.cnblogs.com/cangqiongbingchen/p/9760544.html Vim相关操作 1.基础 * 和 # ...

  9. [转帖]MySQL的又一神器-锁,MySQL面试必备

    MySQL的又一神器-锁,MySQL面试必备 https://segmentfault.com/a/1190000020762791 lock 低一级的是 latch   原文链接:blog.ouya ...

  10. [转帖]Linux中awk工具的使用

    Linux中awk工具的使用 2018年10月09日 17:26:20 谢公子 阅读数 2170更多 分类专栏: linux系统安全   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权 ...

随机推荐

  1. 这场世界级的攻坚考验,华为云GaussDB稳过

    摘要:实践证明,华为云GaussDB完全经受住了这场世界级的攻坚考验,也完全具备支撑大型一体机系统迁移上云的能力,并积累了丰富的经验. 本文分享自华为云社区<这场世界级的攻坚考验,华为云Gaus ...

  2. 详解NLP和时序预测的相似性【附赠AAAI21最佳论文INFORMER的详细解析】

    摘要:本文主要分析自然语言处理和时序预测的相似性,并介绍Informer的创新点. 前言 时序预测模型无外乎RNN(LSTM, GRU)以及现在非常火的Transformer.这些时序神经网络模型的主 ...

  3. 互斥锁Mutex:鸿蒙轻内核中处理临界资源独占的“法官”

    摘要:本文带领大家一起剖析鸿蒙轻内核的互斥锁模块的源代码,包含互斥锁的结构体.互斥锁池初始化.互斥锁创建删除.申请释放等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十 互斥锁Mutex& ...

  4. 火山引擎 DataTester :让字节“跳动”起来的 A/B 实验平台

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流 火山引擎 DataTester 不仅对外提供服务,同时也是当前字节跳动内部所应用的 AB 实验平台. DataTes ...

  5. Jenkins 多分支流水线(SVN)

    实际应用过程中,一般多分支流水线的方式用得比较多一些, master 对应 生成环境 develop 对应 测试环境, 将不同分支的代码构建到不同的环境中 添加 Jenkinsfile 文件 Jenk ...

  6. 多种方式实现 Future 回调返回结果

    JDK  实现 public class FutureTest { public static void main(String[] args) throws Exception { Executor ...

  7. Java Sprintboot jar 项目启动、停止脚本

    将 vipsoft-gateway-1.0.0 替换成自己的包名 start-gateway-dev.sh nohup java -Duser.timezone=GMT+08 -Dfile.encod ...

  8. 解决Github中使用Octotree时,出现 Error: API limit exceeded 报错 或者 Error: Connection error报错的问题(详细操作)

    对于科研工作者来说,Github 是不可多得的利器,那么Octotree 插件的使用将会让用户在使用 Github 时拥有更好的体验,提高学习工作的效率.但是笔者在使用的过程中遇到以下这样的问题,下面 ...

  9. CH0304 IncDec Sequence (差分)

    题目链接: https://ac.nowcoder.com/acm/contest/999/B 思路:(见图中解释) AC代码: #include<bits/stdc++.h> using ...

  10. Redis 缓存性能实践及总结

    一.前言 在互联网应用中,缓存成为高并发架构的关键组件.这篇博客主要介绍缓存使用的典型场景.实操案例分析.Redis使用规范及常规 Redis 监控. 二.常见缓存对比 常见的缓存方案,有本地缓存,包 ...