前言
老规矩,总结一下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 执行操作,具体定位到的行,比如:
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!
$ 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
- 删除空白行
sed '/^$/d' test.txt
- 大小写替换
# 1. 把所有大写变小写:
sed 's/[A-Z]/l&/g' test.txt
# 2. 把所有小写变大写:
sed 's/[a-z]/u&/g' test.txt
- 打印匹配行
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 的数字与字节 |
# 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:]]'