修改我的数据文件中的第一列

时间:2017-09-13 21:15:50

标签: bash awk

我正在尝试修改xyz文件的第一列。我尝试使用awk并且它有效,但它删除了我使用修改后的数据创建的新文件中的一些行。这是原始数据的头部。

1500    
Atoms. Timestep: 0    
1 6.3115 6.3115 6.36745    
2 6.3115 6.3115 9.47036    
2 6.3115 3.15575 6.39316    
2 3.15575 6.3115 6.39316    
3 3.15575 3.15575 8.83622    
4 3.15575 3.15575 3.90335    
5 8.53643 8.92983 8.45625    
5 4.08657 8.92983 8.45625

我使用此代码用另一个文件修改第一列:

awk 'NR==FNR{a[$1]=$2;next} {$1=a[$1]}1' reemp.txt traj300.xyz > tra300.xyz

但现在新文件看起来像这样

Timestep: 0    
Pb 6.3115 6.3115 6.36745    
I 6.3115 6.3115 9.47036    
I 6.3115 3.15575 6.39316    
I 3.15575 6.3115 6.39316    
C 3.15575 3.15575 8.83622    
N 3.15575 3.15575 3.90335    
Hc 8.53643 8.92983 8.45625    
Hc 4.08657 8.92983 8.45625

修改很好,但它删除了第二行的第一行和第一行。问题是该列表有7500万行具有不同的时间步长和配置,并且代码在每个配置中都删除了相同的内容。

2 个答案:

答案 0 :(得分:1)

您的问题是,并非所有traj300.xyz中的字段都可以在reemp.txt中找到。使用input.data的头部我可以使用以下reemp.txt重现您的问题:

1 Pb
2 I
3 C
4 N
5 H

只有在数组中找到该字段时,才应替换第一个字段。您必须在awk

中添加一项检查
awk 'NR==FNR{a[$1]=$2;next} $1 in a {$1=a[$1]}1' reempt.txt traj300.xyz

答案 1 :(得分:0)

您的脚本有两个错误。我已将您的原始数据放入文件input.txt中,并尝试查看您在awk代码的first部分中放入数组a的内容。

$ awk '{a[$1]=$2;next} END {for (i in a) print i"\t-> "a[i]}' input.txt
Atoms.  -> Timestep:         # <- 
1   -> 6.3115
2   -> 3.15575
3   -> 3.15575
4   -> 3.15575
5   -> 4.08657
1500    ->                   # <-

我确定这些并不是您想要的所有值。现在,让我们来看看代码的第二部分:

{$1=a[$1]}

这将替换第一个文件中第2列的每个行的每个第一列,如果您当前的第1列$1可以找到(如果您真的想要我有疑问的话)这个。你想要替换文件2中的第2列吗?)。我们不知道您的第二个输入文件是什么样的,但我们知道的是:

  • 每当第一列=&#34;原子。&#34;它将被&#34; Timestep:&#34;
  • 取代
  • 每当第一列= 1500时,它将被&#34;&#34;
  • 替换

因为您没有向我们提供第二个输入文件,我们不确定您的前两行是什么样的。但是,举个例子,让我们再次输入相同的输入文件:

$ awk 'NR==FNR{a[$1]=$2;next} {$1=a[$1]}1' input.txt input.txt

Timestep: Timestep: 0
6.3115 6.3115 6.3115 6.36745
3.15575 6.3115 6.3115 9.47036
3.15575 6.3115 3.15575 6.39316
3.15575 3.15575 6.3115 6.39316
3.15575 3.15575 3.15575 8.83622
3.15575 3.15575 3.15575 3.90335
4.08657 8.53643 8.92983 8.45625
4.08657 4.08657 8.92983 8.45625

这可能不是你想要做的。我想你需要选择一些行,你真的希望将第一列放入数组a。 您的awk出现的第二错误是它更改了第二个文件中每个第1列。在这里您需要检查 $ 1是否已经在数组a中,然后只有替换它。

那么,也许是这样的?

$ awk 'NR==FNR {if ($1~/[0-9]+/ && $2~/[0-9]+\.[0-9]+/) a[$1]=$2;next} \\ 
($1 in a){$1=a[$1]}1' input.txt input.txt
1500
Atoms. Timestep: 0
6.3115 6.3115 6.3115 6.36745
3.15575 6.3115 6.3115 9.47036
3.15575 6.3115 3.15575 6.39316
3.15575 3.15575 6.3115 6.39316
3.15575 3.15575 3.15575 8.83622
3.15575 3.15575 3.15575 3.90335
4.08657 8.53643 8.92983 8.45625
4.08657 4.08657 8.92983 8.45625

说明:

NR==FNR {                       # only for lines from the first input file
   if ($1~/[0-9]+/ &&           # if column 1 is a number AND  
       $2~/[0-9]+\.[0-9]+/)     # column 2 is a fractional number
      a[$1]=$2;                 # save column 2 in array a with index $1
   next                         # skip to next, for every line in file 1
}
($1 in a){                      # if column 1 exists in array a
  $1=a[$1]                      # replace column 1 by corresponding column 2 from file 1
}
1                               # print line