xargs、awk用法
# xargs 用法
https://www.runoob.com/linux/linux-comm-xargs.html (opens new window)
$ cat b.txt
b1
b2
# 将b.txt中每一行echo出来,不换行
$ cat b.txt | xargs echo
b1 b2
# -I 将xargs前面的输入赋给{},一般是一行一行赋值给 {}
$ cat b.txt | xargs -I {} echo {}.{}
b1.b1
b2.b2
2
3
4
5
6
7
8
9
10
11
12
-a file 从文件中读入作为 stdin -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。 -p 当每次执行一个argument的时候询问一次用户。 -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。 -t 表示先打印命令,然后再执行。 -i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。 -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。 -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。 -L num 从标准输入一次读取 num 行送给 command 命令。 -l 同 -L。 -d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。 -x exit的意思,主要是配合-s使用。。 -P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
# xarg或awk批量解压zip文件, 并为每个zip文件创建对应的文件夹
# 先创建两个zip文件
echo a1 > 1.txt
echo a2 > 2.txt
zip -r 1.zip 1.txt
zip -r 2.zip 2.txt
# $ ls
# 1.txt 1.zip 2.txt 2.zip
# xargs解压文件到 1.zip.folder 2.zip.folder
ls *.zip | xargs -I {} unzip {} -d {}.folder
# awk解压文件到 1 2
ls *.zip | awk -F. '{print "unzip " $0 " -d " $1 }' | bash
# 上面awk如果不加 | bash, 则输出:
unzip 1.zip -d 1
unzip 2.zip -d 2
# awk中print可以用逗号表示空格,看起来更清晰
$ ls *.zip | awk -F. '{print "unzip", $0, "-d", $1 }'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# awk用法
https://www.runoob.com/linux/linux-comm-awk.html (opens new window)
# 指定多个分隔符
- 指定分隔符 awk -F.
- 指定多个分隔符(点和空格) awk -F '[. ]'
通过tcpdump提取pcap包中的纳秒时间戳并转成csv
用tcpdump准备一个txt文件
# 先用tcpdump捕获一个纳秒精度的pcap包
$ tcpdump --time-stamp-precision nano -i any -tt > temp.txt
$ cat temp.txt
1652019592.596857863 IP tcyun.39862 > 101.228.226.13.43500
1652019592.603060220 IP 101.228.226.13.43500 > tcyun.39862
2
3
4
5
6
指定分隔符得到秒和纳秒两个数字并print出来,逗号print出来是空格
$ cat temp.txt | awk -F '[. ]' '{print $1, $2}'
1652019592 596857863
1652019592 603060220
2
3
通过计算得到纳秒 注意最后863变成了856,220变成224最后两位变了,可能是因为浮点数精度的问题
$ cat temp.txt | awk -F '[. ]' '{print ($1*1000000000+$2)}'
1652019592596857856
1652019592603060224
# 为了避免这种精度错误,可以直接print $1 $2
$ cat temp.txt | awk -F '[. ]' '{print $1 $2}'
1652019592596857863
1652019592603060220
2
3
4
5
6
7
8
# printf格式化输出
awk有可能输出科学计数法,比如3e9之类的形式,可通过printf指定格式
$ echo 111.123456789 | awk '{printf("ts=%.4f\n",$1)}'
ts=1121.1235
$ echo 1.123 | awk '{ts=$1+1; printf("ts=%06.3f\n",ts)}'
ts=02.123
2
3
4
5
# awk同时处理多个文件
准备a.txt、b.txt两个文件。处理的时候是每个文件依次按行处理的
$ cat a.txt
a1
a2
a3
$ cat b.txt
b1
b2
# 读取 FNR表示正在读取文件的行数 FILENAME是正在读取的文件名
$ awk 'FILENAME=="a.txt"{printf("in a.txt, line(%d): %s\n", FNR, $1)} FILENAME=="b.txt"{printf("in b.txt, line(%d): %s\n", FNR, $1)}' a.txt b.txt
in a.txt, line(1): a1
in a.txt, line(2): a2
in a.txt, line(3): a3
in b.txt, line(1): b1
in b.txt, line(2): b2
# 上面的 FILENAME也可以换成ARGIND
$ awk 'ARGIND==1{printf("in a.txt, line(%d): %s\n", FNR, $1)} ARGIND==2{printf("in b.txt, line(%d): %s\n", FNR, $1)}' a.txt b.txt
# 上面的 FILENAME也可以FILENAME==ARGV[1] 结果一样
$ awk 'FILENAME==ARGV[1]{printf("in a.txt, line(%d): %s\n", FNR, $1)} FILENAME==ARGV[1]{printf("in b.txt, line(%d): %s\n", FNR, $1)}' a.txt b.txt
# 文件按行合并 注意因为b.txt中只有两行,所以合并下来最终只有两行
$ awk 'FILENAME=="a.txt"{dict_a[FNR]=$1} FILENAME=="b.txt"{print dict_a[FNR], $1}' a.txt b.txt
a1 b1
a2 b2
# 如果要解决上面的问题,可以把a.txt(行数最多的)放在后面
$ awk 'FILENAME=="b.txt"{dict_b[FNR]=$1} FILENAME=="a.txt"{print $1, dict_b[FNR]}' b.txt a.txt
a1 b1
a2 b2
a3
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# awk精度问题
太小的数字会被当做字符串 https://byteofbio.com/archives/1.html
$ echo 2.226e-308 | awk '{if($1<0.05) {print "is small"} else{print "not small"}}'
is small
$ echo 2.225e-308 | awk '{if($1<0.05) {print "is small"} else{print "not small"}}'
not small
# 解决方法: 使用 strtonum() 函数
$ echo 2.225e-308 | awk '{if(strtonum($1)<0.05) {print "is small"} else{print "not small"}}'
is small
2
3
4
5
6
7
8
9
长度超过16的数字计算有问题,末尾超过16位的不对。
# 7个1, 9个3, 9个0
$ echo 1111111 333333333 | awk '{print ($1*1000000000+$2)}'
1111111333333333
# 8个1, 9个3, 9个0
$ echo 11111111 333333333 | awk '{print ($1*1000000000+$2)}'
11111111333333332
# 12个1, 9个3, 9个0
$ echo 111111111111 333333333 | awk '{print ($1*1000000000+$2)}'
111111111111333330944
# 解决方法之一:通过bc命令计算
$ echo 111111111111 333333333 | awk '{printf("%d*1000000000+%d\n", $1, $2)}'
111111111111*1000000000+333333333
$ echo 111111111111 333333333 | awk '{printf("%d*1000000000+%d\n", $1, $2)}' | bc
111111111111333333333
# 解决方法之二:避免超过16位的数字,
# excel在超过15位后会将后面的变为0,小点的数字也方便excel处理
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pandas.dataframe在计算时同样有上述精度问题,计算结果会是256的整数倍
# sed用法
https://blog.csdn.net/wdz306ling/article/details/80087889/ (opens new window)
sed