Bash多文件提取指定字符串至txt失败:sed命令问题修正
提取CAKE_FROSTING首个引号内容的sed命令修正方案
问题背景
在filesToCheck目录下的多个文件中,需要提取所有CAKE_FROSTING()调用里首个双引号(以"表示)内的字符串,并写入result.txt。使用原sed命令时遇到两个问题:
- 即使添加了全局标志
g,每个文件仅能匹配一个CAKE_FROSTING实例; - 命令行可输出部分结果(缺失file3.cpp中的第二个实例),但
result.txt内容为空。
示例文件
file1.cpp
something CAKE_FROSTING("is.simply.the.best", "[no][matter][what]") { DO(something(0) == 1); }
file2.h
something else CAKE_FROSTING( "is.kinda.neat", "[i][agree]") something else something more
file3.cpp
random_text CAKE_FROSTING("Can be nice") "more random text" CAKE_CREAM("totally.sucks", "[trust][me]") random_text CAKE_FROSTING("Can be very nice") "indeed"
期望输出(desiredResult.txt)
is.simply.the.best is.kinda.neat Can be nice Can be very nice
当前命令行输出
is.simply.the.best is.kinda.neat Can be nice
问题原因分析
-z选项的副作用:该选项会将整个文件作为单行处理,搭配贪婪匹配的.*会一次性吞掉文件开头到目标匹配项的所有内容,替换时会覆盖后续所有文本,导致全局标志g无法生效(替换一次后剩余文本已无匹配项);- 重定向为空的可能原因:部分sed版本对
-z模式下的输出处理存在兼容性问题,导致输出无法正确写入文件; - 跨行匹配处理不足:原命令仅用
\n?处理换行,但-z的单行模式下无法正确识别跨行的CAKE_FROSTING结构。
修改后的命令
sed -En '/CAKE_FROSTING/{:a;N;s/.*CAKE_FROSTING\(\s*"([^"]*).*/\1/;Ta;p}' filesToCheck/* > result.txt
关键修改点说明
- 移除
-z选项:恢复逐行处理模式,避免将整个文件作为单行导致的贪婪匹配问题; - 添加跨行匹配逻辑:
/CAKE_FROSTING/{...}:仅处理包含CAKE_FROSTING的行;:a;N;Ta:循环读取下一行,直到捕获到完整的CAKE_FROSTING(...)结构(处理file2.h中跨行的情况);
- 调整正则表达式:
- 用
\s*替代\n?,匹配CAKE_FROSTING(后的任意空白字符(包括换行); - 移除替换末尾的
.*,避免吞掉后续文本,确保能找到多个实例;
- 用
- 移除全局标志
g:改为通过循环跨行读取的方式,确保每个CAKE_FROSTING实例都被单独处理并输出。
内容的提问来源于stack exchange,提问作者JohnFreeman1212
相关产品推荐
相关产品推荐

