如何基于多行正则文件使用sed实现文本末尾替换?
问题:基于多行正则列表的sed批量替换需求
需求说明
想要实现的效果:用file_with_set_of_regexes文件中每行的正则表达式,匹配file_with_data_to_check里的行,给匹配到的行末尾追加some_string,最终结果输出到file_with_processed_data。预期核心逻辑可参考伪代码:
sed -nE "/file_with_set_of_regexes/ s/$/some_string/p" file_with_data_to_check > file_with_processed_data
用户尝试的无效方法
方法1
循环读取正则文件每行执行sed,但无输出也无报错:
for i in `cat ./file_regex`; do sed -En '/`echo "$i"`/ s/$/some_string/p' file_with_data done
方法2
尝试在sed参数中嵌套读取正则的循环,同样无输出无报错:
sed -En -e '/`while read -r ch; do a+=$ch; done <file_regex; echo "$i"`/ s/$/some_string/p' file_with_data
补充情况
当file_regex仅含一行正则时,以下代码可正常运行;但文件含多行正则时,会报错unterminated address regex:
i="$(<file_regex)" sed -nE -e "/$i/ s/\$/some_string/p" file_with_data
测试数据
file_with_data 部分内容
Acetylsalicylic acid Acetylsalicylic acid, combinations excl. psycholeptics Basiliximab BCG vaccine Beclometasone Beclometasone and antibiotics Cefazolin Cefdinir Cyclobenzaprine Cyclopentolate Diosmin Diosmin, combinations Dioxydine* Diphenhydramine Diphtheria antitoxin Diphtheria toxoid
file_regex 部分内容
^(\w+)\*$ [A-Za-z].+combinations [Dd]i((ph)|(f)).+$
运行环境
Windows 7 (x86) Git For Windows 2.34.1.1 (git-bash.exe) GNU bash, version 4.4.23(1)-release (i686-pc-msys) sed (GNU sed) 4.8
可行解决方案
方案1:sed动态生成匹配规则
通过sed把正则文件的每行转换成sed命令,再执行批量匹配:
sed -nE 's|.*|/&/ s/$/some_string/p|' file_regex | sed -nf - file_with_data > file_with_processed_data
- 第一个sed将每行正则
regex转换为/regex/ s/$/some_string/p格式的sed命令 - 第二个sed用
-f -读取标准输入的命令,对目标文件执行匹配替换
方案2:awk实现(逻辑更直观)
用awk读取所有正则存入数组,遍历目标文件每行匹配正则并追加字符串:
awk ' BEGIN { while ((getline reg < "file_regex") > 0) { regexes[++n] = reg } close("file_regex") } { for (i=1; i<=n; i++) { if ($0 ~ regexes[i]) { print $0 "some_string" next } } } ' file_with_data > file_with_processed_data
原方法失效原因
- 方法1中
/echo "$i"/写法错误:单引号内的反引号不会被bash解析,sed实际匹配的是echo "$i"字符串而非变量值 - 方法2的嵌套循环逻辑错误:sed无法解析bash的循环命令
- 多行正则报错:多行正则被拼接成带换行符的字符串,sed的地址正则不允许包含换行,导致语法错误
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

