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

如何在Bash中仅对$EFRAG后的行修改列并添加标签?

处理分子坐标文件的Bash脚本方案

问题描述

原始输入文件内容:

H 1 2 3 4
H 1 2 3 4
C 1 2 3 4
 $END

 $EFRAG
COORD=CART
FRAGNAME=H2ODFT
O 1 2 3 4
H 1 2 3 4
H 1 2 3 4
FRAGNAME=H2ODFT
O 1 2 3 4
H 1 2 3 4
H 1 2 3 4

需要实现的修改:

  1. $EFRAG 行之前的内容保持不变
  2. $EFRAG 行之后的内容:
    • 删除坐标行中的第二列(即那个1)
    • 对每个FRAGNAME=H2ODFT后的三个原子行,分别给O加a、第一个H加b、第二个H加c标签

预期输出:

H 1 2 3 4
H 1 2 3 4
C 1 2 3 4
 $END

 $EFRAG
COORD=CART
FRAGNAME=H2ODFT
Oa  2 3 4
Hb  2 3 4
Hc  2 3 4
FRAGNAME=H2ODFT
Oa  2 3 4
Hb  2 3 4
Hc  2 3 4

解决方案:使用Awk脚本

Awk天生适合这种按行处理且需要状态切换的场景,单命令就能完成所有需求:

awk '
# 标记是否进入$EFRAG之后的处理区域
/^\s*\$EFRAG/ { in_efrag=1; print; next }
# 未进入EFRAG区域时直接输出原内容
!in_efrag { print; next }
# 进入EFRAG区域后的具体处理
{
    # 遇到FRAGNAME行,重置原子计数并直接输出
    if (/FRAGNAME=/) { cnt=0; print; next }
    # COORD行直接输出
    if (/COORD=/) { print; next }
    # 处理原子行:计数递增,匹配对应标签,跳过第二列输出
    cnt++
    tag = (cnt==1) ? "a" : (cnt==2) ? "b" : "c"
    printf "%s%s  %s %s %s\n", $1, tag, $3, $4, $5
}
' input_file > output_file

脚本逐行解释

  • 状态切换:用in_efrag变量区分$EFRAG前后的内容,之前的行直接原样输出
  • 片段初始化:每次遇到FRAGNAME=H2ODFT就重置计数器cnt,确保每个片段内的原子标签循环正确
  • 原子行处理:
    • cnt记录当前片段内的原子顺序(1对应O,2对应第一个H,3对应第二个H)
    • 根据cnt值匹配a/b/c标签,拼接到原子符号末尾
    • 跳过第二列($2),直接输出剩余坐标列,保持格式对齐

关于Sed+Grep的说明

你之前考虑的Sed+Grep组合虽然能实现,但因为需要跟踪片段内的原子顺序,Sed的状态管理会非常繁琐,代码可读性差,不适合新手调试。Awk的方案更直观,也更容易修改扩展。

内容的提问来源于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 15:25:40