如何使用perl搜索两个连续的换行符(\ n)?

时间:2012-01-31 15:20:30

标签: perl replace

如何使用perl搜索两个连续的换行符(\ n)?或者更具体地说,为什么搜索\ n \ n即使它们存在也不成功?我有一个带有连续换行符的文件(用十六进制编辑器验证,它们不是返回等)但是perl似乎不接受这个正则表达式。

perl -pi -e's / \ n \ n / TEST / g'myfile.xml =无结果

我实际上是在尝试将一些代码插入到XML文件中,但是换行符位于中间,这样做最优雅的方式是什么?我想出了一个怪异的perl衬里,但双线馈送似乎导致失败。

我想从以下位置更改gtkrc文件的一部分:

GtkWidget::link-color = @link_color
GtkWidget::visited-link-color = @text_color

####################
# Color Definitions
####################

为:

GtkWidget::link-color = @link_color
GtkWidget::visited-link-color = @text_color

GtkWindow::resize-grip-height = 0
GtkWindow::resize-grip-width = 0

####################
# Color Definitions
####################

使用原始代码的一部分作为我的搜索词(在原始脚本的每行之前有标签,顺便说一句),我的查找和替换术语是:

color\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color

color\n\n\tGtkWindow::resize-grip-height = 0\n\tGtkWindow::resize-grip-width = 0\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color

我想出了这个丑陋的perl命令:

perl -pi -e 's/color\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/color\n\n\tGtkWindow::resize-grip-height = 0\n\tGtkWindow::resize-grip-width = 0\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/g' /usr/share/themes/Ambiance/gtk-2.0/gtkrc

编辑:更正了Zaid的代码:

perl -0777 -pi -e 's/color\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/color\n\n\tGtkWindow::resize-grip-height = 0\n\tGtkWindow::resize-grip-width = 0\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/g' /usr/share/themes/Ambiance/gtk-2.0/gtkrc

如前所述,似乎是\ n \ n导致问题,因为其他任何东西都可以被替换。有什么更好的方法呢?

我在Ubuntu 11.10上,命令将从shell脚本而不是perl脚本运行。

2 个答案:

答案 0 :(得分:3)

您需要一次性加载整个文件,以便检测\n\n。使用-0777覆盖默认的逐行行为:

$ perl -0777 -pi -e 's/\n\n/TEST/g' myfile.xml

答案 1 :(得分:2)

当您打开文件进行读取时,默认情况下会逐行读取该文件。这是因为输入记录分隔符$/设置为换行符。

由于你在换行符中打破了每一行“直线”,因此您无法在一行中连续找到两个换行符。

正如Zaid所说,解决这个问题的一种方法是使用-0标志更改输入记录分隔符。只要新的输入记录分隔符与正则表达式没有部分匹配,您就可以了。 (只要您不尝试将.\n匹配)。

让我们的正则表达式不那么可怕。除非使用#修饰符,否则无需转义/x。您不需要连续使用多个#个字符,而是使用量词+, * or {x,y}

除了删除一个字符串然后放回一个字符串之外,还有一些选项可以避免两次输入相同的内容。

  • 您可以使用Lookaround Assertions来避免删除字符串。
  • 您可以使用\K作为简化的Look-behind断言(见上文)
  • 您可以使用$1, $2 ...捕获字符串并将其放回。

在这种情况下,我的偏好是使用后面的断言来查找“color \ n \ n”字符串,然后查找“Color”注释。

perl -0777 -pwe 's/(?<=color\n\n)(?=[#\s]+Color)/INSERT\n\n/' /path/to/file 

INSERT当然是您要插入的文本,我为了便于阅读而删除了该文本。我还删除了-i标记,以便您可以先试用它。