bash - 搜索匹配项,然后用上一行的值替换此匹配项后的值

标签 bash awk sed

我有多个文件包含以下模式的数千行:

O   HOH     1      11.700 -11.906   1.533
H   HOH     0      12.561 -12.318   1.596
H   HOH     0      11.445 -12.031   0.627
O   HOH     2      17.897   8.999  -0.104
H   HOH     0      18.444   8.521   0.516
H   HOH     0      17.127   8.457  -0.223
O   HOH     3      -0.688  10.310 -15.189
H   HOH     0      -0.760   9.366 -15.055
H   HOH     0      -0.494  10.665 -14.324
O   HOH     4     -10.418   3.733   4.069
H   HOH     0      -9.928   3.726   4.897
H   HOH     0     -11.222   4.218   4.268
O   HOH     5       2.655  -8.910  13.338
H   HOH     0       2.377  -9.739  13.737
H   HOH     0       1.847  -8.531  12.992
O   HOH     6      -0.191  -1.010 -19.469
H   HOH     0       0.455  -1.460 -18.924
H   HOH     0      -0.571  -0.343 -18.895
O   HOH     7      14.338 -15.985  -1.467
H   HOH     0      15.129 -15.647  -1.886
H   HOH     0      13.854 -16.408  -2.175
O   HOH     8     -15.510  -7.073   1.857
H   HOH     0     -15.526  -6.116   1.874
H   HOH     0     -16.341  -7.321   1.464
O   HOH     9       9.155   6.561  -7.729
H   HOH     0       9.419   7.335  -7.245
H   HOH     0       9.943   6.018  -7.768
.
.
.
.
O   HOH  999999     9.155   6.561  -7.729
H   HOH     0       9.419   7.335  -7.245
H   HOH     0       9.943   6.018  -7.768

我需要用 'H HOH xxx' 替换 'H HOH 0' 的每 2 个连续瞬间,其中 xxx 是0 正上方的值

我尝试过的是,我使用

将大文件分成 3 行文件
split -l 3 foo

然后使用 awk 将所需的值复制到另一个文件

awk 'NR==1 print $3' > foo--

然后尝试使用 sed 通过读取文件 foo-- 并替换 foo 中的“0”来替换模式

sed -e '/  0  /{r foo--' -e 'd}' foo 

但是没有用

很确定有更好的方法来做到这一点

最终结果应该是这样的:

O   HOH     1      11.700 -11.906   1.533
H   HOH     1      12.561 -12.318   1.596
H   HOH     1      11.445 -12.031   0.627
O   HOH     2      17.897   8.999  -0.104
H   HOH     2      18.444   8.521   0.516
H   HOH     2      17.127   8.457  -0.223
O   HOH     3      -0.688  10.310 -15.189
H   HOH     3      -0.760   9.366 -15.055
H   HOH     3      -0.494  10.665 -14.324
O   HOH     4     -10.418   3.733   4.069
H   HOH     4      -9.928   3.726   4.897
H   HOH     4     -11.222   4.218   4.268
O   HOH     5       2.655  -8.910  13.338
H   HOH     5       2.377  -9.739  13.737
H   HOH     5       1.847  -8.531  12.992
O   HOH     6      -0.191  -1.010 -19.469
H   HOH     6       0.455  -1.460 -18.924
H   HOH     6      -0.571  -0.343 -18.895
.
.
.
O   HOH     99999      -0.191  -1.010 -19.469
H   HOH     99999       0.455  -1.460 -18.924
H   HOH     99999      -0.571  -0.343 -18.895

最佳答案

您可以在 awk 中做您需要的事情,但是保持格式整洁需要使用 FIELDWIDTHSfprinf。问题是由于 awk 在必须重新计算记录(例如记录更改时)时剥离了前导和尾随 空白。未更改的记录不会以这种方式修改。这在提供表格输出时带来了挑战。

要使用每个字段的 FIELDWIDTHS,请在 BEGIN 规则中提供宽度列表。示例:

awk '
    BEGIN  { FIELDWIDTHS = "1 6 8 10 8 8" }
    $1 == "O" {n = $3}
    $1 == "H" {$3 = n}
    {printf "%s%6s%8s%10s%8s%8s\n", $1,$2,$3,$4,$5,$6}
' file

(注意 FIELDWIDTHS 是一个 GNU awk 特性)

使用您的数据,删除 ...,您只需在命令行复制/鼠标中键粘贴即可进行测试,例如

$ awk '
>     BEGIN  { FIELDWIDTHS = "1 6 8 10 8 8" }
>     $1 == "O" {n = $3}
>     $1 == "H" {$3 = n}
>     {printf "%s%6s%8s%10s%8s%8s\n", $1,$2,$3,$4,$5,$6}
> ' file
O   HOH     1      11.700 -11.906   1.533
H   HOH     1      12.561 -12.318   1.596
H   HOH     1      11.445 -12.031   0.627
O   HOH     2      17.897   8.999  -0.104
H   HOH     2      18.444   8.521   0.516
H   HOH     2      17.127   8.457  -0.223
O   HOH     3      -0.688  10.310 -15.189
H   HOH     3      -0.760   9.366 -15.055
H   HOH     3      -0.494  10.665 -14.324
O   HOH     4     -10.418   3.733   4.069
H   HOH     4      -9.928   3.726   4.897
H   HOH     4     -11.222   4.218   4.268
O   HOH     5       2.655  -8.910  13.338
H   HOH     5       2.377  -9.739  13.737
H   HOH     5       1.847  -8.531  12.992
O   HOH     6      -0.191  -1.010 -19.469
H   HOH     6       0.455  -1.460 -18.924
H   HOH     6      -0.571  -0.343 -18.895
O   HOH     7      14.338 -15.985  -1.467
H   HOH     7      15.129 -15.647  -1.886
H   HOH     7      13.854 -16.408  -2.175
O   HOH     8     -15.510  -7.073   1.857
H   HOH     8     -15.526  -6.116   1.874
H   HOH     8     -16.341  -7.321   1.464
O   HOH     9       9.155   6.561  -7.729
H   HOH     9       9.419   7.335  -7.245
H   HOH     9       9.943   6.018  -7.768
O   HOH  999999     9.155   6.561  -7.729
H   HOH  999999     9.419   7.335  -7.245
H   HOH  999999     9.943   6.018  -7.768

关于bash - 搜索匹配项,然后用上一行的值替换此匹配项后的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58252617/

相关文章:

bash - 如何检查终端中现有的 docker 镜像?

linux - 保留备份

linux - 如何将一系列 AT 命令发送到 bash 中的串口?

shell - 在 AWK 中运行 shell 命令

linux - 如何从文件中提取多行扩展的电子邮件 header

bash - 如何从命令行将每两行合并为一行?

linux - 如何根据大小或内容递归删除 .htaccess 文件

linux - 用于查找搜索计数的 Google API

linux - 在特定位置获取单词后的文本

linux - 删除字符串中 "="之后的所有内容