Bash脚本正则匹配:特定字符串附近不含指定词的行
解决包含特定字符串且前后指定范围无禁止词的匹配问题
看起来你想要筛选出包含目标字符串(比如qwe),并且该字符串前后0-3个字符范围内不出现指定禁止词(比如dfg或qq)的内容。我先帮你分析下当前脚本的问题,再给出正确的实现。
现有脚本的问题
- 循环方式错误:用
for x in $(cat ./test2.txt)会把文件内容按空格拆分成单个单词处理,但你的输入是一整行文本,应该用while read来逐行读取,这样才能处理完整的行。 - 正则逻辑反向:你当前的正则
^.*"$1".\{0,3\}(dfg|qq).*$是在匹配包含目标字符串且后面0-3字符内有禁止词的内容,但你的需求是要排除这种情况,保留符合条件的行。 - 范围不完整:只考虑了目标字符串后面的字符范围,没覆盖前面的部分。
正确的实现方案
下面提供两种方式,一种是修正后的Bash脚本,另一种是更简洁的grep命令实现:
方式1:修正后的Bash脚本
这个脚本会逐行读取文件内容,检查每行是否包含目标字符串,且目标字符串前后0-3个字符范围内没有禁止词:
#!/bin/bash # 开启扩展正则支持 shopt -s extglob # 检查参数是否传入 if [ $# -eq 0 ]; then echo "请传入目标字符串,例如:./test.sh qwe" exit 1 fi target="$1" forbidden_words="dfg|qq" # 逐行处理文件内容 while read -r line; do # 先检查行是否包含目标字符串 if [[ "$line" == *"$target"* ]]; then # 检查是否存在目标字符串前后0-3字符内有禁止词的情况,不存在则输出 if ! [[ "$line" =~ .{0,3}($forbidden_words).{0,3}$target|$target.{0,3}($forbidden_words).{0,3} ]]; then echo "$line" fi fi done < ./test2.txt
方式2:用grep命令直接实现
如果不需要复杂的脚本逻辑,用grep结合Perl正则(-P参数)可以更简洁地完成需求:
grep -P "(?<!.{0,3}(dfg|qq))qwe(?!.{0,3}(dfg|qq))" test2.txt
解释下这个正则:
(?<!.{0,3}(dfg|qq)):否定后顾,确保qwe前面0-3个字符内没有dfg或qqqwe:匹配目标字符串(?!.{0,3}(dfg|qq)):否定前瞻,确保qwe后面0-3个字符内没有dfg或qq
测试效果
对于你的输入内容:qweisdfg qwe is dfg dfg qwe qwe is qq
- 第一个
qweisdfg中,qwe后面第3个字符是d(属于dfg的一部分),所以会被排除 - 后面的
qwe is dfg dfg qwe qwe is qq中,每个qwe前后0-3字符内都没有dfg或qq,所以会被保留,完全符合你的期望输出。
内容的提问来源于stack exchange,提问作者rrkk
相关产品推荐
相关产品推荐

