如何用标准CLI工具提取文本中所有# MODE:开头的代码块?
问题描述
我有一个包含随机内容的文件,其中存在多个如下格式的代码块:
# MODE: bindsym $mod+z mode "$system_mode" mode "$system_mode" { bindsym Return mode "default" bindsym Escape mode "default" } foo # MODE: bindsym $mod+z mode "$other_mode" mode "$other_mode" { bindsym blah blah mode "default" bindsym foo bar "default" } bar
我需要将所有这类代码块提取到另一个文件中。尝试过提取指定模式间内容的sed命令,但只能提取出一个代码块:
sed -e '1,/# MODE:/d' -e '/}/,$d' FILE
该命令返回单个符合格式的代码块,但我需要提取所有符合要求的代码块。优先采用标准CLI工具方案,也可接受Perl或Python实现。
解决方案
方案1:awk(推荐,简洁高效)
通过状态标记匹配所有目标代码块:
awk '/# MODE:/ {in_block=1; next} in_block {print; if (/^}/) in_block=0}' FILE > output.txt
工作逻辑:
- 匹配到
# MODE:时,开启in_block标记并跳过当前行(不需要输出该行) - 标记开启时打印每一行,直到遇到以
}开头的行,关闭标记停止打印 - 结果直接写入
output.txt文件
方案2:sed
利用sed的分支循环处理多个块:
sed -n '/# MODE:/{:a;n;p;/^}/!ba}' FILE > output.txt
工作逻辑:
-n抑制默认输出,只打印指定内容- 匹配到
# MODE:后,进入循环a:读取下一行、打印,若该行不是以}开头则重复循环
方案3:Perl
用Perl的逐行处理实现:
perl -ne 'if (/^# MODE:/) {$f=1; next} if ($f) {print; $f=0 if (/^}/)}' FILE > output.txt
工作逻辑:
- 匹配到
# MODE:时开启标记$f,跳过当前行 - 标记开启时打印行,遇到
}时关闭标记
方案4:Python脚本
适合需要自定义逻辑的场景:
with open("FILE", "r") as infile, open("output.txt", "w") as outfile: in_block = False for line in infile: stripped_line = line.strip() if stripped_line == "# MODE:": in_block = True continue if in_block: outfile.write(line) if stripped_line == "}": in_block = False
使用方法:
将代码保存为extract_blocks.py,替换FILE为你的目标文件名,运行python extract_blocks.py即可。
内容的提问来源于stack exchange,提问作者yPhil
相关产品推荐
相关产品推荐

