首页 > 解决方案 > 从另一个文件替换一个文件中模式之间的列

问题描述

我正在尝试编写读取 file1 的 shell 脚本,从该文件中获取特定列。并将 file2 中的列替换为从两个模式之间的 file1 中提取的列。

文件 1

Line1
Line2
.
LineN
ATOM C1 C2 C3
ATOM P23 HI IKJ
ATOM S23 JSK SN
BOND
Many lines
END

文件2

Few Lines
Pattern1
1 C -9.2429 -1.3783 -9.5091 C.3 1 LIG1 0.0555
2 C -10.5865 -0.8658 -8.9679 C.3 1 LIG1 0.0529
3 N -11.3072 -0.5779 -10.1774 N.am 1 LIG1 -0.2940
Patttern2
Lines

我想从文件 1 中获取列 $2 并将其替换为模式 1 和模式 2 之间的 file2 中的列 $2。

输出

Few Lines
Pattern1
1 C1 -9.2429 -1.3783 -9.5091 C.3 1 LIG1 0.0555
2 P23 -10.5865 -0.8658 -8.9679 C.3 1 LIG1 0.0529
3 S23 -11.3072 -0.5779 -10.1774 N.am 1 LIG1 -0.2940
Patttern2
Lines

到目前为止,我已经尝试了几件事。

awk '($1=="ATOM") {print $2}' file1
awk '/pattern1/{flag=1; next} /pattern2/{flag=0} flag' file2

我可以将第 2 列存储在 file1 中。此外,文件 2 中的两种模式之间的线条。

我确信使用 FNR=NR 之类的东西,我应该能够同时处理这两个文件。任何帮助都会很好地继续进行。

标签: awk

解决方案


根据您的问题和您提到的 (FNR==NR) 解决方案您可以使用此 AWK:

awk '
( FNR==NR && /^ATOM / ) { atoms[++atomn]=$2; }
( FNR!=NR && /^Patttern2$/ ) { doreplace=0; }
doreplace { $2=atoms[++atomn]; }
( FNR!=NR && /^Pattern1$/ ) { doreplace=1; atomn=0; }
FNR!=NR
' file1 file2

在处理元文件和数据文件时,我更喜欢这种方式:

awk '
BEGIN {
  if ( ARGC != 3 ) exit(1);
  while ( getline < ARGV[2] ) if ( $0 ~ /^ATOM / ) atoms[++atomn]=$2;
  ARGC=2;
}
/^Patttern2$/ { doreplace=0; }
doreplace { $2=atoms[++atomn]; }
/^Pattern1$/ { doreplace=1; atomn=0; }
1
' file2 file1

两者都适用于您提供的输入。这里输出:

Few Lines
Pattern1
1 C1 -9.2429 -1.3783 -9.5091 C.3 1 LIG1 0.0555
2 P23 -10.5865 -0.8658 -8.9679 C.3 1 LIG1 0.0529
3 S23 -11.3072 -0.5779 -10.1774 N.am 1 LIG1 -0.2940
Patttern2
Lines

两者都假设在元文件(file1)和数据文件(file2)中,ATOM 和模式之间的行数完全相同。如果您无法验证这一点,我会添加逻辑来观察它,而不是遍历分配的数组元素。然而在 AWK 中什么都不会发生,只是用空字符串替换。


推荐阅读