前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux19-详说linux文本处理(二)

linux19-详说linux文本处理(二)

作者头像
北野茶缸子
发布2022-05-19 11:50:46
8530
发布2022-05-19 11:50:46
举报
文章被收录于专栏:北野茶缸子的专栏

前言

继续总结一下linux 的文本处理。包括但不限于awk, sed, paste,split,grep....

接上文[[18-详说linux文本处理(一)]]

1-paste

paste 可以实现类似R 中paste 的功能,不过其是对文件进行操作:

代码语言:javascript
复制
$ paste -d ':' test3 test4
1:10
2:9
3:8
4:7
5:6
6:5
7:4
8:3
9:2
10:1

其主要选项为:

代码语言:javascript
复制
-d # 指定文件合并的分隔符,默认为tab
-s # 将文件合并后再转置

如果存在不对齐的情况,则paste 会保留空位:

代码语言:javascript
复制
sed -i '2d' test3

$ paste -s test3 test4
1       3       4       5       6       7       8       9       10
10      9       8       7       6       5       4       3       2       1

paste 还有一个比较好用特性,其可以将一个文件拆分为若干列:

代码语言:javascript
复制
$ cat test3 | paste - - -
1       3       4
5       6       7
8       9       10

我经常喜欢对比的一个例子是fq 转fa 的操作:

代码语言:javascript
复制
# awk 高级玩家
awk '{if(NR%4 == 1){print ">" substr($0, 2)}}{if(NR%4 == 2){print}}' fastq > fasta

# paste 偷懒玩家
cat fastq | paste - - - - | awk '{print $1"\n"$4}' | tr '@' '>' > fasta

# sed 勤劳玩家
less -S fastq | awk '{print$1}' | sed -n -e '1~4p' -e '2~4p' | sed 's/@/>/' > fasta

2-awk

上面的awk 是不是看起来很复杂,复杂就对了。这玩意儿贼难用。比sed 还难!

awk 和sed 的结构一样,也是三段式:

代码语言:javascript
复制
awk -options script files

awk 的options 中,-F 用来设置字段分隔符。

这里使用数据:

代码语言:javascript
复制
$ head mtcars2.csv
mpg,cyl,disp,hp,drat,wt,qsec,vs,am,gear,carb
21,6,160,110,3.9,2.62,16.46,0,1,4,4
21,6,160,110,3.9,2.875,17.02,0,1,4,4
22.8,4,108,93,3.85,2.32,18.61,1,1,4,1
21.4,6,258,110,3.08,3.215,19.44,1,0,3,1
18.7,8,360,175,3.15,3.44,17.02,0,0,3,2
18.1,6,225,105,2.76,3.46,20.22,1,0,3,1
14.3,8,360,245,3.21,3.57,15.84,0,0,3,4
24.4,4,146.7,62,3.69,3.19,20,1,0,4,2
22.8,4,140.8,95,3.92,3.15,22.9,1,0,4,2

2.1-基本结构

awk 在读取文本时,会将预定义的字段分隔符划分给每个数据字段,并分配一个变量。awk 默认的字段分隔符为任意空白字符(空格或制表符),可以用 -F 参数定义字段分隔符。字段变量对应关系如下:

代码语言:javascript
复制
$0 代表整个文本行
$1 代表文本中第一个数据字段
...
$NF 代表文本行中的最后一个数据字段

此外,还有如下变量:

代码语言:javascript
复制
FS # 输入字段分隔符,类似-F 参数设定分隔符;
RS # 输入记录分隔符
OFS # 输出字段分隔符
ORS # 输出记录分隔符
NF # 字段总数,比如列数
NR # 输入记录数,比如行数

结合script 中的print 我们可以打印数据的列数,结合wc 了解数据行列:

代码语言:javascript
复制
$ wc -l mtcars2.csv; head -1 mtcars2.csv | awk -F ',' '{print NF}'
33 mtcars2.csv
11

2.2-匹配结构

awk 的匹配结构,和sed 类似,通过/xxx/ 来匹配符合字段的行,并返回输出,接着通过print 打印:

代码语言:javascript
复制
$ cat mtcars2.csv | awk -F ',' '/drat/ {print}' 
mpg,cyl,disp,hp,drat,wt,qsec,vs,am,gear,carb

2.3-拓展结构

我们可以使用BEGIN 与END 语句来对awk 处理的相关内容进行先后设定,相当于 BEGIN >> awk >> END 对应语句依次进行。

代码语言:javascript
复制
$ cat mtcars2.csv | awk -F ',' 'BEGIN{print "---start---"} /18/ {print NR} END{print "---finish---"}'
---start---
4
6
7
11
12
13
14
15
20
23
27
33
---finish---

还可以通过修改内置变量OFS,改变输出分割格式:

代码语言:javascript
复制
$ cat mtcars2.csv | awk 'BEGIN{FS = ",";OFS="\t"} /18/ {print $1,$NF} END{print "---finish---"}'
22.8    1
18.7    2
18.1    1
19.2    4
17.8    4
16.4    3
17.3    3
15.2    3
30.4    2
15.5    2
27.3    1
21.4    2
---finish---

3-awk高级用法

我们可以将awk 的{} 中的内容,当做一个单独的编程语言。

3.1-条件语句

形如:awk '{if (condition) {yes} else {no}}'

代码语言:javascript
复制
$ cat mtcars2.csv | awk 'BEGIN{FS = ",";OFS="\t"} {if ($2 == 8) {print $1,$NF} else {print "it is not equal to 8"}} END{print "---finish---"}' | head
it is not equal to 8
it is not equal to 8
it is not equal to 8
it is not equal to 8
it is not equal to 8
18.7    2
it is not equal to 8
14.3    4
it is not equal to 8
it is not equal to 8

3.2-循环打印

awk '{for (condition) {statement} }'

3.3-数学运算

代码语言:javascript
复制
$ cat mtcars2.csv | awk 'BEGIN{FS = ",";OFS="\t"} {if ($2 == 8) {print $2-$1}} END{print "---finish---"}' | head
-10.7
-6.3
-8.4
-9.3
-7.2
-2.4
-2.4
-6.7
-7.5
-7.2

直接对列计算处理即可,比如:

代码语言:javascript
复制
+, -, *, ^, /

3.4-过滤模式

比如希望过滤文件的第一行,可以使用:

代码语言:javascript
复制
$ awk 'NR == 1 {next} {print $0}' file

当然这个操作sed 也可以实现。

3.5-其他用法

-F 参数可以指定正则,设定多个分隔符,比如:[\t,]

4-tr

将字符进行替换压缩和删除。

  • 替换字符
代码语言:javascript
复制
echo -e 'good \t good' | tr '\t' ';'
good ; good
  • 正则语法,大小写替换
代码语言:javascript
复制
echo "HELLO WORLD" | tr 'A-Z' 'a-z'
hello world
# ‘A-Z’ 和 ‘a-z’都是集合,集合是可以自己制定的,例如:’ABD-}’、‘bB.,’、‘a-de-h’、‘a-c0-9’都属于集合,集合里可以使用’‘、’,可以可以使用其他ASCII字符。
  • 删除字符
代码语言:javascript
复制
echo "hello 123 world 456" | tr -d '0-9'
hello  world 

5-join

和数据库或者其他编程语言中的join 非常类似,就是将文件通过相同的行连接在一起。

代码语言:javascript
复制
$ cd /home/shiyanlou
# 创建两个文件
$ echo '1 hello' > file1
$ echo '1 shiyanlou' > file2
$ join file1 file2
# 将/etc/passwd与/etc/shadow两个文件合并,指定以':'作为分隔符
$ sudo join -t':' /etc/passwd /etc/shadow
# 将/etc/passwd与/etc/group两个文件合并,指定以':'作为分隔符, 分别比对第4和第3个字段
$ sudo join -t':' -1 4 /etc/passwd -2 3 /etc/group

# 也就是以: 分隔passwd 与group 中的内容,其中取前者的第四段和后者的第三段合并

题外话

搜索引擎是个好东西,不会查一下就好了:

如果你想了解awk 与sed,有一本书:

要学习更多的命令,可以参考:Linux 命令大全 | 菜鸟教程[1]

utools 也有个好用的插件:

参考资料

[1]

Linux 命令大全 | 菜鸟教程: https://www.runoob.com/linux/linux-command-manual.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1-paste
  • 2-awk
    • 2.1-基本结构
      • 2.2-匹配结构
        • 2.3-拓展结构
        • 3-awk高级用法
          • 3.1-条件语句
            • 3.2-循环打印
              • 3.3-数学运算
                • 3.4-过滤模式
                  • 3.5-其他用法
                    • 4-tr
                      • 参考资料
                  • 5-join
                  • 题外话
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档