如何让Vim宏根据搜索结果动态执行对应次数?
自动化提取含指定姓名的文本块方案
需求说明
- 核心目标:基于给定姓名列表,从全量文档中提取所有标题包含对应姓名的文本块,保存到新文档
- 当前手动流程:开启三个窗口(筛选结果、全量数据、姓名列表),依次执行:
@l:复制姓名,切换到全量窗口统计匹配行数得到次数n- 手动输入
n@k:重复n次执行文本块定位、复制、粘贴到结果窗口的操作 @j:切换回姓名列表并下移光标
- 痛点:手动输入匹配次数
n,重复操作繁琐,效率极低
方案一:Vim宏自动化优化
通过自定义Vim函数,自动获取匹配次数并执行对应操作,无需手动输入n。
实现步骤
- 在Vim中执行以下脚本(或添加到
~/.vimrc永久生效):
" 自动处理单个姓名的提取函数 function! ExtractNameBlocks() " 复制当前行的姓名 normal! y$ let name = @" " 切换到全量数据窗口 normal! ^W<80>kl " 获取姓名的匹配总行数 let match_count = searchcount({'pattern': name, 'max': 0}).total " 自动执行对应次数的@k宏 execute match_count . '@k' " 切换回姓名列表并下移光标 normal! ^W<80>kr<80>kd endfunction " 绑定快捷键(比如F5),方便快速触发 nnoremap <F5> :call ExtractNameBlocks()<CR>
- 光标定位到姓名列表的第一行,按
<F5>即可自动处理当前姓名;若要批量处理所有姓名,可执行ggVG:call ExtractNameBlocks()<CR>(选中所有姓名行后执行函数)
方案二:Linux终端脚本处理
适合无需打开Vim的批量场景,用awk或grep+sed组合实现高效提取。
前提假设
- 姓名列表文件:
names.txt(每行一个姓名) - 全量文档:
full_data.txt(文本块之间以空行分隔,标题行包含目标姓名)
脚本实现
方法1:通用文本块提取
# 读取姓名列表生成正则匹配式 names_regex=$(paste -sd "|" names.txt) # 提取包含目标姓名的文本块 awk -v regex="$names_regex" ' /^$/ { in_block=0 } in_block { print } $0 ~ regex { in_block=1; print } ' full_data.txt > extracted_results.txt
方法2:带固定标题格式的精准提取
如果全量文档的标题有固定格式(比如以## 开头),可使用更精准的脚本:
awk ' BEGIN { # 加载姓名列表到数组 while ((getline name < "names.txt") > 0) { name_map[name] = 1 } close("names.txt") in_target_block = 0 } # 匹配标题行并检查是否包含目标姓名 /^## / { in_target_block = 0 for (name in name_map) { if (index($0, name) > 0) { in_target_block = 1 print $0 next } } } # 输出当前匹配块的内容 in_target_block == 1 { print $0 } ' full_data.txt > extracted_results.txt
内容的提问来源于stack exchange,提问作者David Robie
相关产品推荐
相关产品推荐

