【问题标题】:Pattern-based substitution in the txt via AWK通过 AWK 在 txt 中进行基于模式的替换
【发布时间】:2018-01-12 03:00:15
【问题描述】:

我有一个长文本文件,其中靠近末尾的某处有 1 行,第 3 列 == OXT。

ATOM   2439  O   LEU   300      -4.699  34.599  65.335  1.00 83.23           O
ATOM   2440  N   LEU   301      -6.822  33.898  65.057  1.00 19.70           N
ATOM   2441  CA  LEU   301      -7.080  34.965  64.138  1.00 19.70           C
ATOM   2442  CB  LEU   301      -8.165  34.630  63.101  1.00 19.70           C
ATOM   2443  CG  LEU   301      -7.762  33.478  62.162  1.00 19.70           C
ATOM   2444  CD1 LEU   301      -8.849  33.207  61.110  1.00 19.70           C
ATOM   2445  CD2 LEU   301      -6.376  33.719  61.543  1.00 19.70           C
ATOM   2446  C   LEU   301      -7.556  36.168  64.946  1.00 19.70           C
ATOM   2447  O   LEU   301      -8.657  36.695  64.633  1.00 19.70           O
ATOM   2448  OXT LEU   301      -6.821  36.580  65.884  1.00 19.70           O
TER    2449      LEU   301
HETATM 2450 NA    NA   302     -13.016  13.036  54.214  1.00 44.33          NA
HETATM 2451  O   WAT   303     -18.411  13.587  59.094  1.00 27.41           O
HETATM 2452  O   WAT   304     -11.894  17.279  58.575  1.00 18.35           O
HETATM 2453  O   WAT   305     -15.811  12.728  54.157  1.00 39.81           O

我需要用 OXT 模式(参见下面的示例)以下列方式修改这一行:在第三列中 - 将“OXT”替换为“N”;在第四列中——用 NHE 代替 ACE;在最后一列中用 N 替换 O。重要的是,在替换之后,我需要保持每列之间的空格数与文件的其余部分相同:

ATOM   2439  O   LEU   300      -4.699  34.599  65.335  1.00 83.23           O
ATOM   2440  N   LEU   301      -6.822  33.898  65.057  1.00 19.70           N
ATOM   2441  CA  LEU   301      -7.080  34.965  64.138  1.00 19.70           C
ATOM   2442  CB  LEU   301      -8.165  34.630  63.101  1.00 19.70           C
ATOM   2443  CG  LEU   301      -7.762  33.478  62.162  1.00 19.70           C
ATOM   2444  CD1 LEU   301      -8.849  33.207  61.110  1.00 19.70           C
ATOM   2445  CD2 LEU   301      -6.376  33.719  61.543  1.00 19.70           C
ATOM   2446  C   LEU   301      -7.556  36.168  64.946  1.00 19.70           C
ATOM   2447  O   LEU   301      -8.657  36.695  64.633  1.00 19.70           O
ATOM   2448  N   NHE   301      -6.821  36.580  65.884  1.00 19.70           N
TER
HETATM 2450 NA    NA   302     -13.016  13.036  54.214  1.00 44.33          NA
HETATM 2451  O   WAT   303     -18.411  13.587  59.094  1.00 27.41           O
HETATM 2452  O   WAT   304     -11.894  17.279  58.575  1.00 18.35           O
HETATM 2453  O   WAT   305     -15.811  12.728  54.157  1.00 39.81           O

我试过用

awk '$3=="OXT"{ f=1; rn=NR; $3=$NF="N"; $4="NHE" }/TER/ && f && NR-rn == 1{ $0=$1 }1' file

它产生了正确的工作,但现在在一个新字符串中,每列之间有 1 个空格,格式错误。

ATOM 2410 N NHE 299 -17.563 -15.711 -15.915 1.00 76.42 N

但是,我需要保持列之间间距的原始格式,就像文件的其余部分一样:

ATOM   2448  N   NHE   301      -6.821  36.580  65.884  1.00 19.70           N

【问题讨论】:

  • 它在替换字符串中产生正确的东西,但破坏了其余文件的某些部分:移动最后两列从而产生伪影。
  • @m47730 关于编辑:没有理由不能用不同的外壳解决这个问题。将答案限制为仅bash 会造成不必要的限制。
  • 下面用 bash 编写的注释中的脚本运行良好!!!它是 bash 和 sed 的组合!

标签: text awk sed


【解决方案1】:

您可以将命令的结果通过管道传递给column 命令:

$>awk  '$3=="OXT"{ f=1; rn=NR; $3=$NF="N"; $4="NHE" }/TER/ && f && NR-rn == 1{ $0=$1 }1' f|column -t
ATOM    2439  O    LEU  300  -4.699   34.599  65.335  1.00  83.23  O
ATOM    2440  N    LEU  301  -6.822   33.898  65.057  1.00  19.70  N
ATOM    2441  CA   LEU  301  -7.080   34.965  64.138  1.00  19.70  C
ATOM    2442  CB   LEU  301  -8.165   34.630  63.101  1.00  19.70  C
ATOM    2443  CG   LEU  301  -7.762   33.478  62.162  1.00  19.70  C
ATOM    2444  CD1  LEU  301  -8.849   33.207  61.110  1.00  19.70  C
ATOM    2445  CD2  LEU  301  -6.376   33.719  61.543  1.00  19.70  C
ATOM    2446  C    LEU  301  -7.556   36.168  64.946  1.00  19.70  C
ATOM    2447  O    LEU  301  -8.657   36.695  64.633  1.00  19.70  O
ATOM    2448  N    NHE  301  -6.821   36.580  65.884  1.00  19.70  N
TER
HETATM  2450  NA   NA   302  -13.016  13.036  54.214  1.00  44.33  NA
HETATM  2451  O    WAT  303  -18.411  13.587  59.094  1.00  27.41  O
HETATM  2452  O    WAT  304  -11.894  17.279  58.575  1.00  18.35  O
HETATM  2453  O    WAT  305  -15.811  12.728  54.157  1.00  39.81  O

【讨论】:

  • 它在替换字符串中产生正确的输出,但会破坏原始文件其余部分的某些部分,在某些部分中,最后两列被移位甚至合并在一起,从而产生错误的输出文件。
  • 可能与fmt 耦合或使用-c 选项?
  • 这样它不起作用 awk '$3=="OXT"{ f=1; rn=NR; $3=$NF="N"; $4="NHE" }/TER/ && f && NR-rn == 1{ $0=$1 }1' 文件 |列-t | fmt
【解决方案2】:

又快又脏:

#/bin/bash

skip=0
cat /tmp/list | while read line
do
  third=$(echo $line | awk '{print $3}')

  if [ $skip -eq 1 ]
  then
    echo "TER"
    skip=0
    continue
  fi

  if [ "${third}" == "OXT" ]
  then
    echo "${line}" | sed 's/OXT/N  /'
    skip=1
    continue
  fi

  echo "${line}"
done

当然 /tmp/list 是包含所有值的文件。

【讨论】:

  • 谢谢!通常它工作正常。但是如何向 sed 添加一个额外的脚本来替换第 4 列(NHE 上的任何树大写字母)和最后一列(将 O 替换为 N)中的值。类似于第 4 列(不幸的是,它也替换了同一字符串的第 1 列,这很糟糕): sed -e 's/OXT/N /' -e 's/[[:upper:]][[:upper: ]][[:upper:]]/NHE/g'
  • @JamesStarlight 用这个新问题更新您的问题;这次还要加上输入和预期输出。以这种描述方式,我不确定是否能达到您的目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 2020-06-24
  • 2013-12-20
相关资源
最近更新 更多