Linux 文本内容处理小记

发布时间:2024年01月11日

这篇笔记用来整理目前用过或者见过的一些文本处理软件,意在提升命令行和脚本对文本处理效率,发现一些可能没关注的实用技巧

简单

先上点简单易用的软件,可以完成基本的文件处理、统计和排序?

wc 统计文本信息

print newline, word, and byte counts for each file? 打印文件的行数,单词数,字符数

可以统计单个文件或多个文件的行数、单词数和字符数,一般用来统计行数用的比较多

wc /etc/passwd /etc/shadow
  46   93 2576 /etc/passwd
  46   46 1897 /etc/shadow
  92  139 4473 total

行数 单词数 字节数 文件名

参数 默认(lwc):
    -c, --bytes
    -m, --chars
    -l, --lines
    -w, --words

ls -l /etc | wc -l

注意:默认的第三个参数,是字节不是字符,写中文就能测试出来默认是-c 不是 -m,但是中文的字节计算不太对

中文在不同编码下占用的字节数不同,在GB2312编码下,一个中文字符占2个字节;在GBK编码下,一个中文字符占2个或4个字节;在UTF-8编码下,一个中文字符占3个或4个字节

echo 打印显示

echo - display a line of text 显示文本中的一行

这个是shell脚本中会经常看到的文本处理命令,也不需要什么复杂的用法,完全可不用特别参数,查看man 也没有太多的参数,不过支持12个转义字符,我取了几个看着有点用的出来

man echo
echo 参数
    -E     disable interpretation of backslash escapes (default) 关闭反斜杠转义支持
    -e     enable interpretation of backslash escapes 开启反斜杠转义支持
    -n     do not output the trailing newline  不打印末尾的换行

If -e is in effect, the following sequences are recognized:
    \\     backslash            打印\
    \n     new line             打印换行
    \r     carriage return      打印回车
    \t     horizontal tab       打印水平制表符
    \v     vertical tab         打印垂直制表符

?echo 参数后面的所有东西都会打印,可以拼接,可以支持取变量,但是注意单引号内原样输出

echo hello world         打印字符
ehco $PATH               打印变量
echo $(hostname)         打印执行结果
echo `hostname`          打印执行结果
echo PATH IS "$PATH"     "" 号内可以取出变量
echo '$PATH'             '' 号内原样输出
echo "hello" -n          打印结果是 hello -n ,参数记得放前面

watch 观察变化

watch - execute a program periodically, showing output fullscreen?定期执行程序,全屏显示输出

这个命令适合用来观察变化,比如文件清单、大小,内容相对固定的文件等等,变化内容可以高亮显示,Ctrl+c 退出

watch 参数:
    -d, --differences        高亮显示变化内容
    -n, --interval seconds   刷新间隔,默认2秒
    -t, --no-title           不显示title
    -e, --errexit            命令执行报错时停止更新,可以按键退出
    -g, --chgexit            命令输出发生变化时退出
    -x, --exec               默认将命令交给sh -c ,需要处理引号,通过exec 可以避免额外引号

man 里面给了几个案例,觉得有点意思

watch -d ls -l
watch -d 'ls -l | fgrep joe'
watch -n 5 -d cat /proc/meminfo

tee 输出重定向

tee - read from standard input and write to standard output and files 获取标准输入写入到标准输出和文件

工作中会发现,有时候需要把执行结果重定向到日志文件,但是也需要观察执行情况,开俩窗口?nohub 其实就可以指定输出到文件和启动时输出到窗口,不过 tee 可能是更好的选择。

tee 参数:
    -a, --append                 追加写入
    -i, --ignore-interrupts      忽略中断信号
    --output-error               如果写入报错,做什么操作
        'warn'            诊断任何写入报错
        'warn-nopipe'     诊断任何写入报错,除了管道输出
        'exit'            写入报错时退出
        'exit-nopipe'     写入报错时退出,除了管道输出

放个自己常用的方式,边看边记录

pidstat -d 5 5 |tee -a pidstat$(date "+%Y%m%d").log


还行

这里记录一些稍微需要花一点点时间的命令,功能相对较复杂一些

cut 内容分割

cut - remove sections from each line of files? ?用指定的字符方式分割文本

有明显且简单的分隔规律时,cut就能满足文本处理需求

cut -d 字符 -f 第几段 filename

date "+%D %H:%M:%S"|cut -d ' ' -f 1
01/11/24

date "+%D %H:%M:%S"|cut -d ' ' -f 1-2
01/11/24 11:13:23
关于参数 -f 取分段
    N        取第N段,计数从1开始,超过最大值就是空
    N-       取第N到最后
    N-M      取N到M段
    -M       取第一段到M段

注意:

1)分隔仅支持一个字符,否则报错?cut: the delimiter must be a single character

2)如果用空格分割,空格不会被合并

3)支持文件和重定向的标准输出

iconv 文本编码转换

iconv - convert text from one character encoding to another 文本编码转换

这个命令的参数很少,帮助文档的案例可以直接拿来用

iconv 参数:
    -l, --list        列出所有已知的字符集编码
    -o outputfile, --output=outputfile   指定输出到文件

    -c         遇到无法解析的字符,直接丢弃而不是终止,也会在 -t 的处理选项生效

    -f from-encoding, --from-code=from-encoding

    -t to-encoding, --to-code=to-encoding
        -t 的编码支持指定遇到无法编码的字符的处理
            //IGNORE        遇到无法编码的字符,丢弃,转换后打印报错
            //TRANSLIT      无法编码会用近似的字符,没有近似字符用?替换

文档案例测试以及发散:?

echo abc ? α € à?? | iconv -f UTF-8 -t ASCII//TRANSLIT
abc ss ? EUR abc

echo abc ? α € à?? | iconv -f UTF-8 -t ASCII//IGNORE
abc    
iconv: illegal input sequence at position 22

echo abc ? α € à?? | iconv -f UTF-8 -t ASCII
abc iconv: illegal input sequence at position 4

echo abc ? α € à?? | iconv -f UTF-8 -t ASCII -c
abc
$ file input.txt
input.txt: ISO-8859 text, with CRLF line terminators
$ iconv -f ISO-8859-1 -t ASCII//IGNORE < input.txt -o output.txt
iconv: illegal input sequence at position 112
$ file *.txt
input.txt:  ISO-8859 text, with CRLF line terminators
output.txt: ASCII text, with CRLF line terminators

?ISO-8859 转 GBK 还是 ISO-8859,UTF-8 转其他不行,因为少了libc.mo 未解决,所以还是得了解一下字符集编码才行呐??man charsets 查看字符集编码的介绍

iconv 报错文件不存在排查:

$ file export.log 
export.log: UTF-8 Unicode text
$ iconv -f UTF-8 -t ISO-8859 < export.log
iconv: failed to start conversion processing: No such file or directory
$ strace iconv -f UTF-8 -t ISO-8859 < export.log
...
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "iconv: ", 7iconv: )                  = 7
write(2, "failed to start conversion proce"..., 37failed to start conversion processing) = 37
write(2, ": No such file or directory", 27: No such file or directory) = 27
write(2, "\n", 1
)                       = 1
exit_group(1)                           = ?
+++ exited with 1 +++
$ locale -a |grep en_US.utf8
en_US.utf8

从strace 追踪结果看得出来,这个文件不存在不是输入文件不存在,是编码的文件不存在,报错的文件确实不存在,但是locale 能查询到UTF-8的支持,yum 里面也找不到 libc.mo 的提供软件。没解决,说是要重装glibc ,算了。。。

libc.mo 是一个包含编译好的本地化字符串的文件,它是与 C 库(libc)一起使用的。本地化字符串是特定于语言环境的文本,例如消息、错误消息和用户界面元素的标签。

tr 字符转换与删除

tr - translate or delete characters 转化或删除字符

看帮助文档,tr 支持用集合来处理字符,用处还是不少滴,还有更复杂的用法,建议看看man?

tr 参数:
    -d, --delete            删除集合1的字符,不转化
    -s, --squeeze-repeats   字符替换 貌似是默认值

例一 把文本小写转大写
$ w | tr -s '[a-z]' '[A-Z]'

例二 打印结果去掉斜杠
$ w | tr -d '/'

例三 去转义字符
$ echo -e 'a \t b'|tr -d '\t'

有点意思

这部分就记录三剑客,grep? awk sed ,平时工作能用的程度还是不难滴,由于过于强大,这里就简单记录一些平时会用到的,后续发现有意思的方式也会持续补充

grep 文本匹配

grep, egrep, fgrep - print lines matching a pattern 打印匹配模式的行

egrep 就是 grep -E,主要是支持正则表达式的意思

fgrep 就是 grep -F ,主要是用通过字符串列表匹配,由换行符分隔,任何换行符都要匹配

grep 平时主要用来过滤文本,能直接用在文件上面,也能通过管道来过滤,日常工作中使用频率很高;支持正则表达式,让 grep 在文本匹配和过滤处理上自由度极高。正则表达式,grep命令的正则有些不同,随后有记录。

grep 的参数很多,能处理文本,文件/目录,能过滤二进制文件,还能读取块设备和套接字,这里只记录一些可能会用到的,更详细的建议看看man grep

grep 参数:

    匹配选项:
        -E, --extended-regexp      正则匹配,扩展规则匹配
        -F, --fixed-strings        字符串(文本段)匹配
        -G, --basic-regexp         基础规则匹配 默认

    匹配控制:
        -i, --ignore-case                   忽略大小写
        -v, --invert-match                  反选
        -e PATTERN, --regexp=PATTERN        使用正则表达式
        -w, --word-regexp                   单词匹配,完全匹配
        -x, --line-regexp                   整行匹配,完全匹配

    输出控制:
        -c, --count                匹配的数量
        -m NUM, --max-count=NUM    读取到文本的第NUM行就停止匹配
        -o, --only-matching        只打印匹配到的内容,而不是过滤到的行
        
        -n, --line-number              打印行号

        -C NUM, -NUM, --context=NUM    打印匹配到的行的前后NUM行
        -A NUM, --after-context=NUM    打印匹配到的行的后NUM行
        -B NUM, --before-context=NUM   打印匹配到的行的前NUM行

    文件和目录:
        -r, --recursive     可以递归的读取目录下的所有文件,没指定目录就是工作目录

        -R, --dereference-recursive  在-r 基础上,还将搜索符号链接指向的目录中的文件
grep -v '#'|grep -v '^$'         过滤注释和空白行
grep -i 'error' messages         查找错误日志,忽略大小写
grep -ri '192.168' /etc/         递归读取目录文件内容,并匹配
grep 'hello' *.log               从多个文件中匹配合适的内容
grep "$HOSTNAME" /etc/hosts      从文件中获取匹配用户名的行

注意:'' 原样输出,"" 可以取值

文件名和工作目录对 grep 的影响

工作中发现,如果工作目录有文件名和grep 的正则参数部分匹配的时候,匹配内容可能会出现意料之外的结果:

$ mkdir archlog rtlog
$ touch rtlog/output.log
$ ls -tR
.:
rtlog  archlog

./rtlog:
output.log

./archlog:

未完待续

文章来源:https://blog.csdn.net/weixin_43839586/article/details/135520968
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。