【问题标题】:Substitution from specify lines of a look up table从查找表的特定行替换
【发布时间】:2025-12-31 01:00:12
【问题描述】:

我正在尝试获取一个脚本来使用 GAMESS 包自动执行一些任务,我希望以后可以从中推断出更复杂的情况。唉,看来我的 Unix 编程技能达不到标准。

我有一个通用的 GAMESS 输入文件 'ion.inp' 的形式:

 $CONTRL SCFTYP=<tag4> ICHARG=<tag5> MULT=<tag6> ISPHER=1 NPRINT=-5 $END
 $BASIS GBASIS=<tag> $END
 $DATA
 <tag1> energy
 Dnh 2

 <tag2> <tag3>  .0  .0  .0
 $END

我(作为 MWE)有一个“ion.inp”参数的查找表,例如“table.dat”,其中 取自表的每一行。

<tag1>          | <tag2> | <tag3> | <tag4> | <tag5> | <tag6>
Hidrogen        | H      | 1.0    | ROHF   | 0      | 2
Hidrogen cation | H      | 1.0    | RHF    | 1      | 1

为了可移植性,我想获得一个使用 POSIX sh、sed 或 awk 的解决方案,但经过一些试验(使用 sh 或 sed,我对 awk 一点也不熟悉,尽管我知道它是一种潜力在这种情况下的解决方案)我无法让它工作。

文件 'ion.inp' 可以就地编辑,因为它将在 sh 循环中运行。除了这个所谓的简单替换之外,我已经完成了所有其他工作。

任何帮助将不胜感激!

【问题讨论】:

  • where the &lt;tag#&gt; are taken from each line of the table.。你怎么知道要从table.dat 表中取什么 row (在你的例子中是 2 或 3)? GBASIS=&lt;tag&gt; 需要做什么?
  • 如果您可以将文件 ion.inp 更改为将标签格式化为 "$tag4" 而不是 &lt;tag4&gt;,事情会更容易。这样你就可以从你的查找中生成一个文件,例如tag4=ROHF 然后将生成的文件包含在ion.inp 中,视为脚本。
  • 替换应该一次循环遍历每一行,从模板创建一个新的 INP 文件。 GBASIS 中的 将循环通过更高的循环,但给出一个工作示例,我可以从中推断出解决方案。
  • 我在编写 MWE 时并没有考虑代码。不过感谢兰金先生的想法。
  • @OsmarTormenaJunior,好吧,最后的评论并没有真正解决我的问题。比如说,给定您的示例文件,结果输出应该是什么样子?

标签: awk sed sh


【解决方案1】:

这是一个使用sedawk 的示例。该脚本名为script.awk。一切都在标准输出上输出,但您可以使用 AWK 脚本中的&gt; 将其重定向到文件。请参阅下面的第二种解决方案。

我们的想法是使用awk 和包含进行替换的数据的table.dat 文件来驱动进程,然后对于每批替换(文件的每一行),我们使用sed 来执行一旦我们有了每个标签和它的值,实际的替换。

  • BEGIN { FS = "\\s*\\|\\s*" } 将字段分隔符更改为使用“可选空格后跟 | 然后再跟可选空格”。这意味着$1$2、...将为我们提供编号为 1、2、...的标签的值
  • NR == 1 { next } 用于跳过无用的第一行,因为标签从 1 开始排序,没有任何间隙。如果不是这样,我们将不得不调整 AWK 脚本。
  • { ... } 为每一行我们构建sed 命令并执行它。 sed 的输出成为该特定行的 awk 的输出。
BEGIN { FS = "\\s*\\|\\s*" }
NR == 1 { next }
{
  s = ""
  for (i=1; i <= NF; i++)
    s = s sprintf(";s/%s/%s/g", "<tag" i ">", $i)
  system("sed '" s "' ion.inp")
}
$ cat table.dat
<tag1>          | <tag2> | <tag3> | <tag4> | <tag5> | <tag6>
Hidrogen        | H      | 1.0    | ROHF   | 0      | 2
Hidrogen cation | H      | 1.0    | RHF    | 1      | 1
$ cat ion.inp
$CONTRL SCFTYP=<tag4> ICHARG=<tag5> MULT=<tag6> ISPHER=1 NPRINT=-5 $END
$BASIS GBASIS=<tag> $END
$DATA
<tag1> energy
Dnh 2

<tag2> <tag3>  .0  .0  .0
$END
$ awk -f script.awk table.dat
$CONTRL SCFTYP=ROHF ICHARG=0 MULT=2 ISPHER=1 NPRINT=-5 $END
$BASIS GBASIS=<tag> $END
$DATA
Hidrogen energy
Dnh 2

H 1.0  .0  .0  .0
$END
$CONTRL SCFTYP=RHF ICHARG=1 MULT=1 ISPHER=1 NPRINT=-5 $END
$BASIS GBASIS=<tag> $END
$DATA
Hidrogen cation energy
Dnh 2

H 1.0  .0  .0  .0
$END

使用命令awk -f script2.awk table.dat 重定向到文件。脚本script2.awk是:

BEGIN { FS = "\\s*\\|\\s*" }
NR == 1 { next }
{
  s = ""
  for (i=1; i <= NF; i++)
    s = s sprintf(";s/%s/%s/g", "<tag" i ">", $i)
  system("sed '" s "' ion.inp > " sprintf("output%02d.txt", NR-1))
}
$ cat output01.txt
$CONTRL SCFTYP=ROHF ICHARG=0 MULT=2 ISPHER=1 NPRINT=-5 $END
$BASIS GBASIS=<tag> $END
$DATA
Hidrogen energy
Dnh 2

H 1.0  .0  .0  .0
$END
$ cat output02.txt
$CONTRL SCFTYP=RHF ICHARG=1 MULT=1 ISPHER=1 NPRINT=-5 $END
$BASIS GBASIS=<tag> $END
$DATA
Hidrogen cation energy
Dnh 2

H 1.0  .0  .0  .0
$END

【讨论】: