我正在尝试创建一个filter命令来减少日志文件中的行,假设每一行都包含由日期、组成的分区
/iamthepath01/20200301/file01.txt
/iamthepath02/20200302/file02.txt
....
/iamthepathxx/20210619/filexx.txt
然后从成千上万的行中,我只想保留路径中有两个字符串的行
/202106
/202105
并删除任何其他线路
我已经试着按照命令
sed -i -e '(/202105|/202106)!d' ~/log.txt
以上命令抛出
sed: -e expression #1, char 24: unterminated address regex
您可以使用
sed -i '//20210[56]/!d' ~/log.txt
或者,如果你需要使用更具体的替代方案并进一步增强模式:
sed -i -E '//(202105|202106)/!d' ~/log.txt
详细信息:
-i
-用于内联文件替换的GNU sed选项-E
-启用POSIX ERE regex语法的选项//20210[56]/
-匹配/20210
,然后匹配5
或6
的正则表达式/(202105|202106)
-匹配/
,然后匹配202105
或202106
的POSIX ERE模式!d
-删除与图案不匹配的线条
查看在线演示:
#!/bin/bash
s='/iamthepath01/20200301/file01.txt
/iamthepath02/20200302/file02.txt
/iamthepathxx/20210619/filexx.txt'
sed '//20210[56]/!d' <<< "$s"
输出:
/iamthepathxx/20210619/filexx.txt
sed是错误的工具。如果你想要一个像sed一样脆弱的脚本,那么就使用grep,因为它是一个只用于执行简单g/re/p
(因此得名(的工具,就像你正在做的那样:
$ grep '/20210[56]' file
/iamthepathxx/20210619/filexx.txt
或者,如果你想要一个更强大的解决方案,只关注你想要匹配的行的部分,从而避免错误匹配,那么使用awk:
$ awk -F '/' '$3 ~ /^20210[56]/' file
/iamthepathxx/20210619/filexx.txt
这可能对你有用(GNU sed(:
sed -ni '#/20210[56]#p' file
这使用类似seds-n
grep的选项来关闭隐式打印,使用-i
选项来就地编辑文件。
通常sed使用/.../
进行匹配,但如果转义了第一个分隔符,则可以使用其他分隔符,例如#...#
。
因此,上面的解决方案将把现有文件过滤到包含/202105
或/202106
的行。
N.B.grep几乎肯定会更快地找到上述线条,然而-i
选项的使用可能是选择sed的最终原因(尽管通过将> tmpFile && mv tmpFile file
附加到grep解决方案可以实现相同的结果(。