regex - 带有正则表达式的 grep-bash 命令返回 0 个结果,正在寻找替代方案
问题描述
我正在尝试在 linux bash 中编写一些东西来导出模式以及带有有用信息的标头。例如,如果我正在阅读的源文件看起来像:
test1
test2
test3 KJHKKJKLKJJKKKKJJHJLKLKJJHHKLJHJKLHLHLHLJLKJHHKLKJHLKJHKLLJHJHKLKJJHKLLKJHJKLLKJHHKKLLKKKKKLKJHHKLLJJHHKKLLKJHJKLJJHHKLKJHJLJJKLKLJHJKKLLLJJKLLKJKLJJJLKJHJHJKKLLKJJHKLJHKLLJHHKKLKJHKKLKJJHJKLLJHHKKLLJJHJHKLJJKKHJ
test4 LKJKLLLKJHKLKLJLJKJJLKJKKHKHKHLJLHHLKLJKLHLJLKHLKJLHLHLHLKJHLKHLKHLKJLJLHLKJLJLHLJKLKHLJHJLHLHJLKJJLKHLKHLKHLKHLKJJLJLJLHLKLKJLJLLHJKHLKHLHLJHLJHLJHLJHLHLJLKJLKJLJHHJHKJHKJHKJHKKHKHKHJLJLLJLJHKHKJHKJHKJHKJHKJHJLJLJLHLJHLKLKHLKHKLKLKHKKHLKHLHH
我的模式字符串是 KKHKHKH
我要返回:test2 KJKJKJKJKLJJKJJKLLLKKJJKLJJHJKKKKHKHKH
测试4 LKJKLLLKJHKLKLJLJKJJLKJLJLHHLKLJKLHLJLKHLKJLHLHLHLKJHLKHLKHLKJLJLHLKJLJLHLJKLKHLJHJLHLHJLKJJLKHLKHLKHLKHLKJJLJLJLHLKLKJLJLLHJKHLKHLHLJHLJHLJHLJHLHLJLKJLKHKJHKJHHJ
关键是在模式处结束,而不是下面的测试。序列中也可能存在重复。我想写入每个测试标题下的最远匹配(测试 4 中的示例)
我们在课堂上学习了 grep,所以我使用 grep 和扩展正则表达式 -E 或 egrep 来尝试解决问题。我知道在一些论坛上有人尝试过 sed。
我试过用 grep -E 'test|KKHKHKH' file.txt 运行它
grep -E '>test\d+\n[LKJH]*KKHKHKH' file.txt 我再次通过调试器运行它,这次我的表达是错误的,我想我以某种方式搞砸了格式,但它之前工作过:(。只是在 bash 中不起作用
我再次期望输出是:
test2
KJKJKJKJKLJJKJJKLLLKKJJKLJJHJKKKKHKHKH
测试4 LKJKLLLKJHKLKLJLJKJJLKJLJLHHLKLJKLHLJLKHLKJLHLHLHLKJHLKHLKHLKJLJLHLKJLJLHLJKLKHLJHJLHLHJLKJJLKHLKHLKHLKHLKJJLJLJLHLKLKJLJLLHJKHLKHLHLJHLJHLJHLJHLHLJLKJLKHKJHKJHHJ
但是对于第一个表达式 grep -E 'test|KKHKHKH' file.txt 我得到:
test1
test2
KJKJKJKJKLJJKJJKLLLKKJJKLJJHJKKKKHKHKH
test3
test4
LKJKLLLKJHKLKLJLJKJJLKJLJLHHLKLJKLHLJLKHLKJLHLHLHLKJHLKHLKHLKJLJLHLKJLJLHLJKLKHLJHJLHLHJLKJJLKHLKHLKHLKHLKJLJLJLHLKLKJLJLLHJKHLKHLHLJHLJHLJHLJHLJLKJLKJHKJHHHJHK
我需要以某种方式只获取 test2 和 test 4 我想我可以通过 grep 再次管道它,但不知道如何获得标题。我在想我可以使用 -B 并计算前面的行数。但是每个序列可能会稍大一些。
对于最后一个表达式,我没有返回任何内容,尽管它似乎至少在某个时间点在 regex101 调试器中工作...... :(
如果没有简单的 grep 表达式,是否有我可以尝试的 bash 脚本?
解决方案
grep
一次检查一行输入。因此,需要跨越换行符的正则表达式将永远不会匹配(没关系,\n
这并不意味着 支持的正则表达式方言中的换行符grep
)。你想要类似的东西
awk '/^test/ { t=$0 }
/KKHKHKH/ { print t; print }' file.txt
如果文件总是包含test
在匹配之前的上一行,你也可以说
grep -B 1 'KKHKHKH' file.txt
尽管这也会在您可能不想要的匹配之间产生一些输出。
如果匹配总是跟在我的空行之后,则对 Awk 脚本的小修改应该可以只获得每个块中的最后一个匹配:
awk '/^test/ { t=$0 }
/KKHKHKH/ { p=$0 }
/^$/ && p { print t; print p; t=p="" }
END { if(p) { print t; print p }}' file.txt
END
如果在最后一个块之后也肯定有空行,则该块可能是不必要的;但是在这种情况下错过最后一场比赛是一个常见的错误,并且保护措施相当简单(尽管我很懒并且产生了一些重复的代码)。
推荐阅读
- django - 如何让用户在线支付费用
- python - Python - 根据 JSON 中的值从 JSON 中删除重复元素
- c# - 如何在检查器中使用字符串插值?
- typescript - 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引
- javascript - 如何通过搜索栏 React Native 搜索 FlatList?
- html - CSS网格中列的反转顺序
- c - 带有 Zip 插件的 Cordova iOS 应用程序编译 - 未找到 aes/aes.h
- javascript - 如果 JavaScript 中有条件,如何使用 forEach 循环返回 true
- python - 在 python 中运行函数后,切片对象作为参数没有改变
- laravel - 使用带有 Laravel eloquent 和多个 where 子句的 Haversine 公式