You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bash中为特定OHH行组上方插入FRAGNAME=H2ODFT行?

问题描述

我是Bash脚本新手,之前用下面的命令能在所有以O开头的行前插入FRAGNAME=H2ODFT:

for EFP in *.inp; do
    sed -i "/^O */i FRAGNAME=H2ODFT" $EFP
done

但现在需要仅在连续的O、H、H三行(带笛卡尔坐标)前插入该行,而非所有O行。试了sed多行匹配没效果:

for FILE in *.inp; do
    sed -i "/^O*\nH*\nH */i FRAGNAME=H2ODFT" $EFP
done

还试过awk也没成功。

输入示例:

C           36.116           34.950           34.657
     C           35.638           34.681           35.883
     ...(省略部分内容)
     O           40.889           37.054           35.401
     H           40.304           36.361           35.706
     H           41.620           36.587           34.995

期望输出:

...(省略部分内容)
     FRAGNAME=H2ODFT
     O           40.889           37.054           35.401
     H           40.304           36.361           35.706
     H           41.620           36.587           34.995
可行解决方法

方法1:GNU Sed 多行匹配

sed默认单行处理,需要通过N命令读取后续行构建多行匹配,以下命令可实现需求:

for EFP in *.inp; do
    sed -i -E 'N;N;/^[[:space:]]*O[[:space:]]+.+\n[[:space:]]*H[[:space:]]+.+\n[[:space:]]*H[[:space:]]+/i FRAGNAME=H2ODFT' "$EFP"
done
  • -E:启用扩展正则,简化匹配语法
  • N;N:读取当前行之后的两行,将三行内容放入模式空间
  • 正则部分精准匹配"空格+O+坐标"→换行→"空格+H+坐标"→换行→"空格+H+坐标"的结构
  • i命令在匹配到的行组前插入指定文本

方法2:Awk 缓存行处理

awk处理多行逻辑更直观,通过缓存最近三行内容检测OHH序列:

for EFP in *.inp; do
    awk '
        {
            line1 = line2
            line2 = current
            current = $0
        }
        /^[[:space:]]*H/ && line1 ~ /^[[:space:]]*O/ && line2 ~ /^[[:space:]]*H/ {
            print "     FRAGNAME=H2ODFT"
            print line1
            print line2
        }
        NR>2 { print current }
        NR<=2 { if (NR==2) print line1; if (NR==1) print current }
    ' "$EFP" > temp.inp && mv temp.inp "$EFP"
done
  • 用line1/line2/current三个变量缓存最近三行
  • 检测到连续OHH时,先插入目标行,再输出缓存的O和H行
  • 最后处理剩余行,确保所有内容完整输出
  • 由于awk无法直接修改原文件,先输出到临时文件再替换原文件

方法3:GNU Sed -z 参数(简洁版)

GNU Sed的-z参数可将整个文件读入内存,支持全局多行替换:

for EFP in *.inp; do
    sed -i -z 's/^[[:space:]]*O[[:space:]]+.+\n[[:space:]]*H[[:space:]]+.+\n[[:space:]]*H[[:space:]]+/     FRAGNAME=H2ODFT\n&/mg' "$EFP"
done
  • -z:将文件视为单字符串处理
  • 替换规则中,&指代匹配到的OHH行组,在其前插入目标行和换行符
  • mg:开启多行匹配和全局替换模式

内容的提问来源于stack exchange,提问作者Lucielle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 03:40:21