多行正则表达式

Posted

技术标签:

【中文标题】多行正则表达式【英文标题】:Regular Expression over multiple lines 【发布时间】:2011-05-29 11:45:54 【问题描述】:

我已经为此坚持了几个小时,并循环使用了大量不同的工具来完成工作。没有成功。如果有人能帮我解决这个问题,那就太好了。

问题来了:

我有一个格式不正确的非常大的 CSV 文件 (400mb+)。现在它看起来像这样:

这是一个描述某事的长摘要。下面是这句话的拼贴。”
,标题1
这是在一行上运行的另一个句子。在下一行,您可以找到标题。
,标题2

您可能会看到标题“,Title1”和“,Title2”实际上应该与上述句子在同一行。然后它看起来像这样:

这是一个描述某事的长摘要。下面是这句话的拼贴。",Title1
这是在一行上运行的另一个句子。在下一行你可以找到标题。,Title2

请注意,句尾可以包含引号,也可以不包含引号。最后它们也应该被替换。

这是我到目前为止的想法:

sed -n '1h;1!H;$;g;s/\."?.*,//g;p;' out.csv > out1.csv

这实际上应该完成匹配多行表达式的工作。不幸的是它没有:)

表达式正在寻找句子末尾的点和可选的引号以及我试图与 .* 匹配的换行符。

帮助非常感谢。用什么工具来完成工作并不重要(awk、perl、sed、tr 等)。

【问题讨论】:

您有不是特定领域的示例吗?我无法查看您到底想要更改什么。 罗伯特,我改变了这个例子。我希望这个更好:) 你的 csv 真的只有 2 个字段还是只是一个简化的例子? 现在只有这两个字段。 【参考方案1】:

sed 中的多行本身并不一定很棘手,只是它使用了大多数人不熟悉的命令并且具有某些副作用,例如用 '\n' 分隔当前行和下一行当您使用 'N' 将下一行附加到模式空间时。

无论如何,如果你匹配以逗号开头的行来决定是否删除换行符会容易得多,所以这就是我在这里所做的:

sed 'N;/\n,/s/"\? *\n//;P;D' title_csv

输入

$ cat title_csv
don't touch this line
don't touch this line either
This is a long abstract describing something. What follows is the tile for this sentence."
,Title1
seriously, don't touch this line
This is another sentence that is running on one line. On the next line you can find the title.
,Title2
also, don't touch this line

输出

$ sed 'N;/\n,/s/"\? *\n//;P;D' title_csv
don't touch this line
don't touch this line either
This is a long abstract describing something. What follows is the tile for this sentence.,Title1
seriously, don't touch this line
This is another sentence that is running on one line. On the next line you can find the title.,Title2
also, don't touch this line

【讨论】:

谢谢。您的示例对我有用,但由于某种原因它不适用于我的文件。虽然图案基本相同。我已将一个小示例上传到我的 Dropbox。也许你知道这里出了什么问题。 dl.dropbox.com/u/84641/temp/text.csv @herrherr 好的,找到并修复。在我的原始代码中,我使用\+ 匹配空格一次或多次,我真正想要的是* 匹配空格 次或更多次。 @herrherr:我发现在从 DropBox 下载的文件中添加尾随换行符后,这个 (sed 'N;/\n,/s/\n,/,/' text.csv) 对我有用。 如果在 ",Title1" 行之后有 "don't touch" 行,这将失败。它也不能消除虚假报价。 @Dennis 两个帐户都很好。我对删除尾随引号的部分完全感兴趣。至于奇怪的配对,只需一点P;D 的爱就可以支撑它。【参考方案2】:

你的作品有几个小改动:

sed -n '1h;1!H;$;g;s/\."\?\n,//g;p;' inputfile

? 需要转义,. 不匹配换行符。

这是另一种不需要使用保留空间的方法:

sed -n '$p;q;N;/\n,/s/"\?\n//p;b;P;D' inputfile

这是一个注释版本:

sed -n '
$          # for the last input line

  p;             # print
  q              # and quit
;
N;         # otherwise, append the next line
/\n,/      # if it starts with a comma

  s/"\?\n//p;    # delete an optional comma and the newline and print the result
  b              # branch to the end to read the next line
;
P;         # it doesn't start with a comma so print it
D          # delete the first line of the pair (it's just been printed) and loop to the top
' inputfile

【讨论】:

在我回复您的评论后才注意到您的帖子。不需要循环并且特别注意最后一行。只需将P;D 附加到我的脚本末尾即可。

以上是关于多行正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

Python: 正则表达式匹配多行,实现多行匹配模式

perl正则表达式怎么匹配多行?

多行格式化的 JavaScript 正则表达式 [重复]

匹配多行文本块的正则表达式

正则表达式去除 phpdoc 多行注释

Python 3 正则表达式查找多行注释