【问题标题】:How to replace last n characters in the kth occurence of a line containing a certain substring using sed or awk?如何使用 sed 或 awk 替换包含某个子字符串的第 k 次出现的最后 n 个字符?
【发布时间】:2017-09-11 11:35:14
【问题描述】:

假设我有一个类似于以下格式的文件:

\\ Random other lines \\
...
27861NA+    NA+89122  13.480  11.554  10.082
27862NA+    NA+89123   2.166   5.896  10.108
27863NA+    NA+89124   8.289   6.843   3.090
27864NA+    NA+89125  12.972   5.936   4.498
27865CL-    CL-89126  13.914   2.125  12.915
27866CL-    CL-89127  12.050  13.907   3.559
...
\\ Random other lines \\

对于文件中包含字符串“NA+”的前 3 个行实例,我正在尝试用我准备好的字符串替换每行的最后 24 个字符。

例如,理想情况下,我的输出应如下所示:

\\ Random other lines \\
...
27861NA+    NA+89122  my first string  hello
27862NA+    NA+89123  my second string foo  
27863NA+    NA+89124  my final string bar $$
27864NA+    NA+89125  12.972   5.936   4.498
27865CL-    CL-89126  13.914   2.125  12.915
27866CL-    CL-89127  12.050  13.907   3.559
...
\\ Random other lines \\

到目前为止,我已经找到了一个 sed 命令,它可以删除文件中每一行的最后 24 个字符:

sed 's/.\{24\}$//' myfile.txt

还有一个 awk 命令,它将返回包含所需子字符串的第 k 行:

awk '/NA+/{i++}i==1' myfile.txt

有没有人知道如何替换文件的第 1、第 2 和第 3 行中每个包含特定子字符串的最后 24 个字符?

【问题讨论】:

  • 使用与文件中的字符串“NA+”匹配的 shell 变量创建一个循环运行 3 次。还要比较行数以避免再次匹配同一行。

标签: bash awk sed


【解决方案1】:

awk

awk -v str="my string" '!f && /NA\+/{ f=1; n=NR+3 }n && n>NR{ $4=$5=""; $3=str }1' myfile.txt

【讨论】:

  • 这会修改所有包含 NA+ 子字符串的行,不仅是前 3 行,而且还错误地修改了包含 NA+ 的最后一行之后的前三行
  • 这是(样本)我的实际输出: ... 27860NA+ NA+89121 我的字符串 27861NA+ NA+89122 我的字符串 27862NA+ NA+89123 我的字符串 27863NA+ NA+89124 我的字符串 27864NA+ NA+89125 my string 27865CL- CL-89126 my string 27866CL- CL-89127 my string 27867CL- CL-89128 my string 27868CL- CL-89129 2.617 4.968 11.497 27869CL- CL-89130 4.954 3.078 4.030 27870CL- CL-89131 9.233 3.081 1.208 ...
  • 啊,是的,你一直都是对的——我真诚的道歉。
  • @Ecaloota,没关系
  • @Ecaloota 您没有要在输出中使用的 3 个 不同 字符串,前 3 行 NA+ 行中的每行一个吗?这就是您问题中的示例所显示的内容。
【解决方案2】:
string="my first string hello"
awk -v string="$string" '{ if ( $0 ~ "NA" ) {cnt++} if (cnt < 4 ) { print substr($0,1,length($0)-23)string } else { print }}' NA

使用 awk,设置一个字符串并使用 -v 将其传递给 awk。搜索包含 NA 和递增变量 cnt 的字符串。当 cnt 小于 4 时,打印除最后 23 个字符之外的所有内容,并将字符串添加到末尾。否则打印该行。

【讨论】:

    【解决方案3】:

    这可能对你有用(GNU sed):

    sed '/NA+/{x;s/\n/&/3;x;ta;H;s/.\{24\}$/some string/;b;:a;n;ba}' file
    

    这使用保持空间 (HS) 来记录脚本已经看到的所需字符串 (NA+) 的行数。一旦它看到 n (在这种情况下 n = 3)这样的行,它只会打印文件的其余部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-07
      • 2020-02-18
      • 2015-06-08
      • 1970-01-01
      • 1970-01-01
      • 2011-05-17
      • 2020-08-16
      • 1970-01-01
      相关资源
      最近更新 更多