Grep进阶匹配:如何在指定位置包含无字符及自定义分隔模式
问题解答
关于「无字符」作为可选匹配项的实现
你原来的命令grep "${beg}"'[-_*]'"${rem}"里,方括号[-_*]仅用于匹配单个字面字符(连字符、下划线或星号),无法覆盖「无字符」场景——因为方括号的作用是定义单个字符的匹配集合,空字符不在这个范畴内。
要实现beg和rem之间可以是「无字符」,或是-/_,需调整正则结构:
- 若使用grep默认的基础正则:
其中grep "${beg}\([-_]\)\{0,1\}${rem}"\([-_]\)\{0,1\}表示匹配0次或1次-/_,0次就对应「无字符」的情况。 - 若使用更简洁的扩展正则(需加
-E选项):grep -E "${beg}([-_])?${rem}"([-_])?中的?表示前面的分组可选(匹配0或1次),完美覆盖「无字符」或单个-/_的需求。
匹配四种目标情况的正则调整
要实现仅匹配beg和rem之间为以下四种情况之一:-、_、无字符、-(空格-连字符-空格),用扩展正则最清晰:
grep -E "${beg}([-_]| - |)?${rem}"
这里的([-_]| - |)?表示:要么匹配-/_,要么匹配-,要么什么都不匹配(对应无字符),整个分组通过?标记为可选。
注意:如果beg或rem本身包含正则元字符(比如.、*、$等),需要先对它们做转义处理,避免干扰正则匹配。可通过sed 's/[.[\*^$]/\\&/g'完成转义。
结合启动盘索引搜索的脚本实现思路
基于上述正则逻辑,脚本可按以下思路实现:
- 定义起始字符串
beg和结束字符串rem,并对两者做正则元字符转义。 - 生成目标正则模式:
"${escaped_beg}([-_]| - |)?${escaped_rem}"。 - 遍历系统启动盘的所有分区(可通过
lsblk -lno NAME,MOUNTPOINT | grep -v '^loop'筛选非循环挂载的启动盘分区)。 - 对每个分区的预建索引文件/目录执行grep搜索。
示例脚本片段:
#!/bin/bash beg="your_start_string" rem="your_end_string" # 转义正则元字符 escaped_beg=$(printf '%s' "$beg" | sed 's/[.[\*^$]/\\&/g') escaped_rem=$(printf '%s' "$rem" | sed 's/[.[\*^$]/\\&/g') pattern="${escaped_beg}([-_]| - |)?${escaped_rem}" # 遍历启动盘分区的挂载点 lsblk -lno NAME,MOUNTPOINT | grep -v '^loop' | while read -r name mountpoint; do if [ -n "$mountpoint" ] && [ -d "$mountpoint" ]; then # 假设预建索引是每个分区下的.index文件,可根据实际场景调整 index_file="${mountpoint}/.index" if [ -f "$index_file" ]; then echo "搜索分区 $name ($mountpoint) 的索引文件:" grep -E "$pattern" "$index_file" fi fi done
内容的提问来源于stack exchange,提问作者Eric Marceau
相关产品推荐
相关产品推荐

