如何批量将文件中某行路径复制到另一行指定位置?
批量修改TeX文件路径的sed/awk实现方案
需求说明
有大量格式相似的TeX文件,示例原内容如下:
a line of text % !TEX TS-parameter = ../ a line of text a line of text a line of text \gresetgregpath{{music/}} a line of text a line of text
需要完成的修改:提取% !TEX TS-parameter = 后的相对路径(如示例中的../),将其插入到\gresetgregpath{{与music/}}之间,修改后效果如下:
a line of text % !TEX TS-parameter = ../ a line of text a line of text a line of text \gresetgregpath{{../music/}} a line of text a line of text
约束条件:每个文件中% !TEX TS-parameter = 和\gresetgregpath{{music/}}均只出现一次,不同文件的相对路径各不相同。
方案一:sed实现
利用sed的保持空间(hold space)存储捕获的路径,再完成替换:
单文件处理命令
sed -i.bak -n ' # 捕获路径行,提取路径存入保持空间 /% !TEX TS-parameter = / { s/.*= //; h; p; b } # 处理目标行,取出保持空间的路径拼接替换 /\\gresetgregpath{{music\/}}/ { g; s/\(.*\)/\\gresetgregpath{{\1music\/}}/; p; b } # 其他行直接输出 p ' your_tex_file.tex
-i.bak:原地修改文件,同时生成.bak后缀的备份文件(若无需备份,可改为-i)-n:关闭默认行输出,通过p手动控制输出内容- 第一块逻辑:匹配到路径行时,删除
% !TEX TS-parameter =前缀,将剩余路径存入保持空间,打印原路径行后跳过后续处理 - 第二块逻辑:匹配到目标行时,取出保持空间的路径,拼接成新行后打印,跳过后续处理
- 最后的
p:打印所有未被上述块处理的普通行
批量处理当前目录下所有.tex文件
for file in *.tex; do sed -i.bak -n ' /% !TEX TS-parameter = / { s/.*= //; h; p; b } /\\gresetgregpath{{music\/}}/ { g; s/\(.*\)/\\gresetgregpath{{\1music\/}}/; p; b } p ' "$file" done
方案二:awk实现
awk的变量存储更直观,适合处理这类跨行关联的修改(需GNU awk支持,macOS可通过brew安装gawk):
单文件处理命令
awk -i inplace -v bak=".bak" ' # 捕获路径行,提取路径存入变量path /% !TEX TS-parameter = / { path = substr($0, index($0, "=")+2); print; next } # 替换目标行,拼接路径后输出 /\\gresetgregpath{{music\/}}/ { print "\\gresetgregpath{{" path "music/}}"; next } # 其他行直接打印 1 ' your_tex_file.tex
-i inplace -v bak=".bak":原地修改文件并生成备份- 第一块逻辑:匹配到路径行时,用
substr提取=后的路径内容,打印原路径行后处理下一行 - 第二块逻辑:匹配到目标行时,拼接路径生成新行并打印,处理下一行
1:awk中非0值等价于print,用于打印所有普通行
批量处理当前目录下所有.tex文件
for file in *.tex; do awk -i inplace -v bak=".bak" ' /% !TEX TS-parameter = / { path = substr($0, index($0, "=")+2); print; next } /\\gresetgregpath{{music\/}}/ { print "\\gresetgregpath{{" path "music/}}"; next } 1 ' "$file" done
内容的提问来源于stack exchange,提问作者rpspringuel
相关产品推荐
相关产品推荐

