linux字符处理

0

前言

大部分项目在部署后都会项目中添加日志文件一些记录文件,而我们经常需要分析或者处理相关文件中的字符,所以掌握linux字符处理命令非常重要。

举个例子:后端提供某个接口,接收请求的时候其中一个参数死活收不到,但你确信这个参数是百分百已发送的,于是你查看请求记录日志文件,找出所有发送记录数据,与后端同学一起排错(撕逼)。

再举个例子:某个文件中存储了许多用户相关的数据,现在要将这些数据写入数据库中,但是这些数据中有很多重复数据,并且这些数据中有很多无用符号等。如果在程序中对文件不停的进行查找与替换数据,必然会拖慢程序的速度,如果使用linux命令把文件中的重复数据与无用数据给清楚,是不是处理器来就方便很多了。

创建两个简单文件,分别为1.txt、2.txt,下文用这两个文件来做示范

# 1.txt
a:aa1
B:b1
xxx
c:c1
xxx
d:d1
:end
# 2.txt
a:a2
b:b2
xxx
c:c2
xxx
d:d2
:end2

管道

输油管、输气管是现实生活中的管道,linux中也存在管道,它是一个4KB的缓存区,当我们要输出的文件内容太多的情况下在终端中可能会翻屏的现象导致之前的内容不能查看,这个时候管道就可以派上用场了。

举个例子,查看系统程序二进制文件bash内容

more /bin/bash

# 查看目录清单,如果目录清单够多的话,也会触发管道
ls -a | more

clipboard.png

因为“/bin/bash”是二进制文件,所以上图中出现了乱码;
在内容超出4KB的情况下输出结果中会出现冒号,键盘上下键可来回翻看,是不是像一根管道呢;

查找字符

grep regex [file...] [-RiVlnc]
# -R: 文件夹递归查找模式
# -i:查找匹配时忽略大小写
# -V:显示不匹配的行
# -l:列出匹配模式的文件名称
# -n:列出检索目标所在的行号
# -c:统计匹配的行总数,不显示行信息

grep以行为单位查找,
包含3个参数,“regex”为字符串或者正则表达式, “file”为文件或者文件夹名,-R为结果筛选选项。

基础用法

# 查找带“:”的内容
grep ":" 1.txt

clipboard.png

按正则表达式查找

# 查找符合正则表达式的数据行
grep "^\\w\{1\}:\\w\{1,2\}$" 1.txt

clipboard.png

  • “a:aa1”并未出现在查找结果中,因为结尾不符合正则{1,2}
  • 正则表达式有”通配符“与“POSIX”两种风格
  • 正则表达式中非普通字符,使用“”进行转义,否则会被当做普通文本处理

文件夹递归查找

# test 表示文件夹
grep "^\\w\{1\}:\\w\{1,2\}$" test -R
# 查找内容太多的情况下可以使用管道
grep "^\\w\{1\}:\\w\{1,2\}$" test -R | more

内容排序

sort [file] [-urontkkfbc]
#u 去重
#r 降序
#o 写入文件
#n 以数字顺序排列
#t 设定查找分隔符
#k 一般与-t一起使用,用来按照第几列来排序
#f 忽略大小写
#b 忽略每一行前列空白
#c 内容是否已排序

基础用法

sort 1.txt

sort将文件的每一行作为一个单位,默认按照首字母SCII码值排序,很多的时候排序返回结果并不符合我们的需求,所以需要用到sort提供的其他选项了。

分隔内容排序

# 按照冒号分隔内容,并且使用第2列数据进行排序,不存在第二列数据的情况下,linux默认使用空字符串填充
sort -t: -k 2 1.txt

排序内容输出到新的文件

# 使用-o选项
sort 1.txt -o new1.txt;
# 当然也可以使用 >
sort 1.txt > new2.txt

去重

uniq [-i-c]
# -i 忽略大小写
# -c 查找行数
uniq 1.txt

clipboard.png

返回结果中存在两个“xxx”,是uniq去重指的是连续两行或者多行相同的内容,所以uniq一般都是与sort配合一起使用。

sort 1.txt -u
sort 1.txt | uniq

截取文本

cut [-df]
# -d 自定义分隔符
# -f 指定的列,一般与-d一起使用
cat 1.txt | cut -d ':' -f 2

使用了 -f 参数如果指定列不存在,程序首先会查找分隔符是否存在,如果整行数据中存在分隔符的情况下则使用空格代替,如果不存在则使用整行数据返回输出。

文本转换

tr [-cdst]
# -s squeeze-repeats:把连续重复的字符以单独一个字符表示;例如“aa”=>“a”
# -d delete:删除所有属于第一字符集的字符;
# 小写转化为大写
cat 1.txt | tr "[a-z]" [A-Z]
# 如果两个“a”字符连在一起会被当做一个“a”处理
cat 1.txt | tr -s "a" "z"
# 删除数字字符集
cat 1.txt | tr -d "[0-9]"
# 删除“a”与“:”
cat 1.txt | tr -d "a:"

tr命令只能按照按照字符集映射替换处理,比如“a-A,b=>”,不支持正则表达式。
也不支持连续的字符串替换成特定的字符串,比如“abc”替换成“xyz”,如果这样进行处理的话,程序会进行映射替换“a=>x,b=>y,c=>z”。
tr命令比较简单,但是功能太弱了,一般值用来替换删除大小写数字之类比较特殊的字符映射替换。

文本合并

paste [-d] [file] [targetFile]
# -d 合并分隔符,默认为“ ”空格字符串
# 普通合并
paste -d “1.txt” "2.txt"
# 设置分隔符为“:”,
paste -d ":" "1.txt" "2.txt" > "new.txt"

文本合并并不是将b文本内容附加在a文本内容后面,而是将b文本每一行内容附加在a文本对应行号内容后面。
文本合并使用场景很少。

文件分割合并

文件分割

split [-bl] [filename] [target_prefix]
# -b 按大小分割
# -l 按行数分割
# 按每个文件大小2k进行分割
split -b 2k "1.txt" "new"
# 按每个文件5行文本进行大小分割
split -l 5 "1.txt" "new"

二进制文本是没有行号的,只能按大小分割

文件合并

cat new* > "target.txt"

使用场景举例

当上传或者下载较大文件时,传输不停中断而不得不重新传输,可以先将大文件分割成小文件后分批传输,传完后再合并文件。


参考资料

正则表达式

你可能感兴趣的

载入中...