linux18-详说linux文本处理(一)

2022-05-19 11:50:19 浏览数 (1)

前言

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

1-split

参考:[Linux split命令 | 菜鸟教程 (runoob.com)](https://www.runoob.com/linux/linux-comm-split.html "Linux split命令 | 菜鸟教程 (runoob.com "Linux split命令 | 菜鸟教程 (runoob.com)")")

使用起来非常简单。主要有以下选项:

代码语言:javascript复制
-l # 直接指定若干行切成一个文件
-b # 指定字节切割
-a # 分割后的文件尾数,默认是2,比如 aa,ab,ac
-d # 用数字替代尾数而非字母,比如00,01,02

尝试一下:

代码语言:javascript复制
$ wc -l test.txt 
100 test.txt

$ mkdir split_test_output

$ split test.txt -l 5 -d -a 3  split_test_output/test_

$ ls split_test_output/
test_000  test_002  test_004  test_006  test_008  test_010  test_012  test_014  test_016  test_018
test_001  test_003  test_005  test_007  test_009  test_011  test_013  test_015  test_017  test_019

你可以根据wc 或less -SN 获得你的文件行数,然后通过split 指定拆分成若干个包含行数的文件。

ps:貌似mac 下的split,有些选项被阉割掉了。

2-sed

如果说split 仅仅是对文本内容进行拆分,那么sed 就是一个强大的定位于行进行增删改查的“软件”了。

其语法形如:

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

选项如下:

代码语言:javascript复制
-n # 只显示经过sed 处理后的行;
-f # 从文件中获取sed 执行代码;
-r # sed 匹配加入正则功能;
-i # 直接对文件修改,并不输出;

之所以称为“软件”,正是因为其可以通过script 字段进行sed 专门的编程。

sed 的script 格式为address command,其中address 表示sed 执行操作,具体定位到的行,比如:

代码语言:javascript复制
2 # 第二行
2,6 # 二到六行
2,$ # $ 表示最后
2~3 # 第二行开始,间隔三行取一行
2, 4 # 从第二行到第六行(二加四)
/pattern/ # 匹配上pattern 字段的行
[!] # 取反

而command 则是专门的sed 语句模式:

代码语言:javascript复制
a # 在指定行后增加一行,内容为a 后面跟随的字符内容
i # 在指定行前增加一行,内容为i 后面跟随的字符内容
d # 删除若干行,可以是选定的或匹配的行
p # 直接将sed处理的行打印出来
s # 替换,语法为`s/old/new/[flags]`,将old 替换为new,默认替换匹配到的第一个old 字段,可以设置flags 为g 全局替换
y # 转换,在字符层面进行替换,`y/a/A/`

说了如此多抽象的说明,来实战一下吧。

代码语言:javascript复制
❯ cat test.txt
1
We Are Good! HHHHH!
2
yes, I do.
3
4
5
6
7
8
9
10
  • 在指定字段前添加内容 比如添加Welcome!
代码语言:javascript复制
$ sed '1~3a Welcome!' test.txt
1
Welcome!
We Are Good! HHHHH!
2
yes, I do.
Welcome!
3
4
5
Welcome!
6
7
8
Welcome!
9
10
  • 删除空白行
代码语言:javascript复制
sed '/^$/d' test.txt
  • 大小写替换
代码语言:javascript复制
# 1. 把所有大写变小写:
sed 's/[A-Z]/l&/g' test.txt

# 2. 把所有小写变大写:
sed 's/[a-z]/u&/g' test.txt
  • 打印匹配行
代码语言:javascript复制
cat test.txt | sed -n '/Good/p'

不过这个匹配功能,自然比不上下面的grep了。

3-grep

大名鼎鼎的正则匹配查找工具。那自然是要学会一定的正则语法了:

代码语言:javascript复制
需要强调的是,正则表达式的字符范围包括大小写字母,罗马数字,以及部分符号。

. 表示任何单个字符(换行符外)
[] 对单个字符给出取值范围;[abc]表示a或b或c,[a-f]表a-f中的任意一个字符串。
[^ ],与[]相反,指取值范围以外字符;[^abc]表示非a非b非c。
*,前一个字符0或无限延伸;abc*表示,ab,abc,abcc...
 ,前一个字符1或无限延伸;abc 表示,abc,abcc,abccc...
?,前一个字符0或1次延伸;abc?表示,ab,abc。
|,左右表达式任意一个;ab|cd表示,ab或cd。
{m},扩展前一个字符串m次;ab{2}c,表示abbc。
{m,n},扩展前一个字符串m 到n次;ab{1,2}c,表示abc,abbc。
^,表示字符串开头部分;^abc,匹配abc 开头的字符串。
$,匹配字符串结尾;abc$,匹配abc 结尾的字符串。
(),分组标记,内部只可以用|;(abc)表示abc,(abc|def)表示abc, def。
d 数字,等价于[0-9]
D 非数字。
w 单词字符,等价于[A-Z], [a-z], [0-9] 及 -。
W 非单词字符。
t 制表符。
n 空行。
s 空格型内容,如t, n等。
S 非空格。

我曾经写过:[[13-正则表达式简明学习指南]]

grep 有以下好用的选项:

代码语言:javascript复制
-w # 精确查找
-c # 统计成功匹配的行数
-v # 反向匹配,输出未匹配到的内容
-f # 从指定文件中匹配
-i # 忽略匹配的大小写
-n # 显示匹配成功的行号
-r # 从指定目录中的全部文本文件中匹配

test.txt 的第3行:

代码语言:javascript复制
❯ grep -n -w 3 -r ./
.//test.txt:3:3

shell 中,还有一些自己的特殊符号:

特殊符号

说明

[:alnum:]

代表英文大小写字母及数字,亦即 0-9, A-Z, a-z

[:alpha:]

代表任何英文大小写字母,亦即 A-Z, a-z

[:blank:]

代表空白键与 [Tab] 按键两者

[:cntrl:]

代表键盘上面的控制按键,亦即包括 CR, LF, Tab, Del.. 等等

[:digit:]

代表数字而已,亦即 0-9

[:graph:]

除了空白字节 (空白键与 [Tab] 按键) 外的其他所有按键

[:lower:]

代表小写字母,亦即 a-z

[:print:]

代表任何可以被列印出来的字符

[:punct:]

代表标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $...

[:upper:]

代表大写字母,亦即 A-Z

[:space:]

任何会产生空白的字符,包括空白键, [Tab], CR 等等

[:xdigit:]

代表 16 进位的数字类型,因此包括:0-9, A-F, a-f 的数字与字节

代码语言:javascript复制
# grep默认是区分大小写的,这里将匹配所有的小写字母
$ echo -e '1234nabcd' | grep '[a-z]'
# 将匹配所有的数字
$ echo -e '1234nabcd' | grep '[0-9]'
# 将匹配所有的数字
$ echo -e '1234nabcd' | grep '[[:digit:]]'
# 将匹配所有的小写字母
$ echo -e '1234nabcd' | grep '[[:lower:]]'
# 将匹配所有的大写字母
$ echo -e '1234nabcd' | grep '[[:upper:]]'
# 将匹配所有的字母和数字,包括0-9,a-z,A-Z
$ echo -e '1234nabcd' | grep '[[:alnum:]]'
# 将匹配所有的字母
$ echo -e '1234nabcd' | grep '[[:alpha:]]'

0 人点赞