【问题标题】:Replace the line above a matched pattern替换匹配模式上方的行
【发布时间】:2015-09-07 23:48:41
【问题描述】:

我有一个 html 文件,其中有一个表格,如下所示:

<td>unknown</td> <td>blah11</td> ... <td>unknown</td> <td>blah24</td> ...

我需要匹配 'blah24' 并将上面的 'unknown' 替换为 'test' 给出:

<td>test</td> <td>blah24</td>

我曾尝试研究 sed 和 awk 解决方案,但只能找到“在匹配模式之前插入”或“在匹配模式之后替换”。

我只有在使用 cygwin 的独立机器上可用的基本 shell 工具。

【问题讨论】:

  • 如果你使用tac,它会向后打印文件,然后你可以使用“替换下一行技巧”,使用tac file | awk ..

标签: regex shell awk sed


【解决方案1】:
$ awk 'NR>1{if(/blah24/) sub(/unknown/,"test",prev); print prev} {prev=$0} END{print prev}' file
<td>unknown</td>
<td>blah11</td>
...
<td>test</td>
<td>blah24</td>
...

如果blah24 出现在较长字符串的一部分,或者您真的想专门替换unknown 或者只是标签中的任何内容或其他各种重要细节,您没有告诉我们该怎么做,但希望您可以综上所述,弄清楚所有这些。

【讨论】:

  • 感谢您的快速回复。 blah24 将是该 html 文件中的唯一 ID。我想专门替换始终出现在唯一 ID 上方的 unknown 并将内容写回原始文件。
  • 好的,但blah241fooblah24 也可以存在于文件中吗? foounknownbar 怎么样?如果是这样,你想用这些做什么?使用任何 UNIX 命令写回原始文件是cmd file &gt; tmp &amp;&amp; mv tmp file。 GNU sed 有一个 -i 选项,而 GNU awk 有 -i inplace 但它们都只是在幕后做同样的事情。
  • 很好,我想出了几乎相同的逻辑,但在 sed 中。 +1 :)
【解决方案2】:

在 sed 中你可以这样做

sed -n '/blah24/{x;s/unknown/test/;x};x;1!p;${x;p}' file

<td>unknown</td>
<td>blah11</td>
...
<td>test</td>
<td>blah24</td>
...

它将当前行交换为保持缓冲区的每一行。如果找到 blah24,则交换保留的行,将其更改为测试,然后将其交换回来。它打印除 1 之外的每一行(因为它会打印一个空格)。

【讨论】:

  • 我发现这个 sed 命令与 Ed Morton 包含的 -i 选项一起完成这项工作。谢谢!
猜你喜欢
  • 2023-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2013-04-07
  • 2010-11-02
  • 2012-05-04
相关资源
最近更新 更多