替换单词取决于第二行

替换单词取决于第二行

我有一个网表文件。它有分割线。分割符号是位于续行开头的“+”。

MP1 Y A VDD VDD pch_25 W=1u L=550n M=1
MP0 Y B
+VDD VDD pch_25 W=1u L=550n M=1
MN1 v0 A VSS VSS nch_25_dnw W=500.0n L=550n M=1
MN0 Y B v0 VSS nch_25_dnw W=500.0n L=550n M=1

如果该(完整)行包含“pch_25”,我想用“X”替换每行的开头“M”,因此所需的输出是

XP1 Y A VDD VDD pch_25 W=1u L=550n M=1
XP0 Y B
+VDD VDD pch_25 W=1u L=550n M=1
MN1 v0 A VSS VSS nch_25_dnw W=500.0n L=550n M=1
MN0 Y B v0 VSS nch_25_dnw W=500.0n L=550n M=1

我有以下(工作)命令:

sed -e :a -e '$!N;s/\n+/\\/;ta' -e 'P;D' file \
                                        | sed '/pch_25/s/^M/X/' | sed -e 's/\\/\n+/g'

如何用一个sed没有管道的命令替换这个命令?

答案1

N;P;D通常,您会使用 in模式执行类似的任务sed,以始终将缓冲区中的两行保持在一起。不幸的是,网表文件可以将一条记录拆分为多行,因此通常的解决方案将不起作用。

显而易见的解决方案是添加一个循环来收集属于在一起的所有行:

sed -e :a -e '/pch_25/s/^M/X/;/\n[^+]/!{N;ba' -e '};P;D' file           
  • /pch_25/s/^M/X/是我们要执行的实际替换:在包含 的行中pch_25s将前导(^锚点)替换MX
  • 该模式\n[^+]定义了一个换行符,后跟一些除 之外的其他字符+,这表明我们添加了太多行并且必须退出循环。换句话说,如果我们用 反转匹配!,我们可以附加下一行Nba跳转到循环标记:a
  • 最后,通常P;D打印并删除缓冲区的第一行,并开始一个新的循环。是的,如果我们已经在缓冲区中收集了两行以上,则只有第一行会被打印和删除。但没问题:下一个周期不会替换任何内容,因为模式将以+, not开头M,其他行将被相继删除

先进的解决方案: 现在我有一个想法,将N;P;D模式扩展为多行,没有跳转标记和b.这个想法是D通过在模式的开头添加换行符来使用for 循环,换行符可以通过以下方式删除D(注意:这是 GNUsed代码):

sed '/pch_25/s/^M/X/;/\n[^+]/!N;//P;//!s/^/\n/;D' file
  • /\n[^+]/!N如果我们仍然在同一个网络记录中,则添加换行符
  • //重复最后一个模式,这里没有反转,所以如果我们添加太多一行,我们可以P打印第一部分
  • //!s/^/\n/如果我们仍在一条记录中,则在模式的开头添加一个换行符,所以最后的
  • D如果我们必须检查替换,则将在重新开始之前仅删除添加的空行,或者如果我们已经在下一条记录中,则删除已打印的第一行

不幸的是,替换中使用的\n是 GNU 的非标准添加sed,因此您不能依赖它,而必须找到另一种方法来添加换行符,例如附加到保留空间、清空模式空间和x更改空间:

sed '/pch_25/s/^M/X/;/\n[^+]/!N;//P;//!{H;s/.*//;x;};D' file

相关内容