sed 文档

linux grep/sed 匹配不起作用

  • 在某些情况下,sed和grep的可能无法正常工作
  • 其中,我认为最大的可能就是编码或者控制字符的问题

匹配异常案例

我在Windows端用powershell的函数创建了一个包含多个时间戳的文件

生成引发问题的powershell脚本
Write-Output 'clear the old content...'
# ''>text1
# remove empty line:
Clear-Content .\text1

Write-Output 'generating n lines content'
1..100 | ForEach-Object {
    # $_.ToString()>>.\text1
    # $_.ToString() >> text1
    # "$_"+"line+$(gdt.ticks)">>text1
    "L$($_)$((Get-Date).Ticks)">>.\text1
    # $_
}
# "teset">>text1

cat 的查看选项

关于控制符/空白字符/非打印字符显示
 -v, --show-nonprinting
              use ^ and M- notation, except for LFD and TAB
-E, --show-ends
              display $ at end of each line
  -T, --show-tabs
              display TAB characters as ^I
 -A, --show-all
              equivalent to -vET
引发问题的文本文件
表面内容
  • 在linux端查看,文件内容表面上看是:(cat )
��L82637834872061501239
L83637834872061511251
L84637834872061521729
L85637834872061531253
L86637834872061531253
L87637834872061543390
L88637834872061543390
L89637834872061553069
L90637834872061564965
L91637834872061574806
L92637834872061584797
L93637834872061595208
L94637834872061597156
L95637834872061607141
L96637834872061617478
L97637834872061627133%
实际内容
  • 实际内容(cat -A)却是
M-^?M-~L^@8^@2^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@0^@1^@2^@3^@9^@^M^@$
^@L^@8^@3^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@1^@1^@2^@5^@1^@^M^@$
^@L^@8^@4^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@2^@1^@7^@2^@9^@^M^@$
^@L^@8^@5^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@3^@1^@2^@5^@3^@^M^@$
^@L^@8^@6^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@3^@1^@2^@5^@3^@^M^@$
^@L^@8^@7^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@4^@3^@3^@9^@0^@^M^@$
^@L^@8^@8^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@4^@3^@3^@9^@0^@^M^@$
^@L^@8^@9^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@5^@3^@0^@6^@9^@^M^@$
^@L^@9^@0^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@6^@4^@9^@6^@5^@^M^@$
^@L^@9^@1^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@7^@4^@8^@0^@6^@^M^@$
^@L^@9^@2^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@8^@4^@7^@9^@7^@^M^@$
^@L^@9^@3^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@9^@5^@2^@0^@8^@^M^@$
^@L^@9^@4^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@5^@9^@7^@1^@5^@6^@^M^@$
^@L^@9^@5^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@6^@0^@7^@1^@4^@1^@^M^@$
^@L^@9^@6^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@6^@1^@7^@4^@7^@8^@^M^@$
^@L^@9^@7^@6^@3^@7^@8^@3^@4^@8^@7^@2^@0^@6^@1^@6^@2^@7^@1^@3^@3^@%

正常内容

(清洗处理过的内容)的cat -A查看

L82637834872061501239^M$
L83637834872061511251^M$
L84637834872061521729^M$
L85637834872061531253^M$
L86637834872061531253^M$
L87637834872061543390^M$
L88637834872061543390^M$
L89637834872061553069^M$
L90637834872061564965^M$
L91637834872061574806^M$
L92637834872061584797^M$
L93637834872061595208^M$
L94637834872061597156^M$
L95637834872061607141^M$
L96637834872061617478^M$

sed 调试

  • 使用sed 的debug功能也可以发现编码问题

nl & cat -n

  • 使用nl 和cat -n 处理文件在输入给sed处理会造成意料之外的结果
  • 例如
nl input.txt |sed '/^b.d/p'  -n > output.txt

该操作理论上是看不到任何东西,因为,nl 命令会为文本的各行行首添加行号(阿拉伯数字),导致文本和源文件中读取的不同;

  • 下面这种做法不会造成匹配问题(但是输出的行号会和源文件中的行号不一致
    cat input.txt |sed '/^b.d/p' -n|nl|tee output.txt

总结

  • 使用linux的grep/sed的时候,当一些基本的正则匹配无法达到预期效果,可以通过cat -A来检查文件中的控制字符,这种异常经常发生在windows端的文件传输到linux上处理的时候;(尤其是通过windows的某些脚本生成的文本,更容易含有看不见的控制符号,从而影响sed/grep等工具的工作效果.
  • 大该是因为,powershell是面向对象的shell,某些输出会出人意料

可能的解决办法

  • 如果情况如上所述,那么可以考虑使用powershell 的cat 命令来清洗多余的控制符号(另存清洗后的文件),例如cat file> washedVersionFile

shell脚本文件运行不起来/报错

  • 有些时候,linux上的shell脚本会运行不起来(主要是指,语法上没有问题,外观上确实没甚么问题&逻辑上也没有问题,但就是执行就报错
  • 这种情况一般出现在,脚本文件不是在linux环境编写的
  • 特别是,在windows上编写的脚本,通常无法直接在linux直接运行

可能的原因

  • 回车符/换行符的问题:
  • 在vscode中,我们可以通过将CRLF改为LF后再编辑文件
  • 在这里插入图片描述
错误示例
cxxu@cxxuAli:~$ ./deploy.sh 
./deploy.sh: line 1: cd: $'/home/cxxu/backEnd/\r': No such file or directory

vim/neovim for windows

  • 除了powershell下处理的文件,windows下的其他编辑器(vim)可能也有控制符号的问题
Logo

更多推荐