Regex sed-如何获得段落的前两个句子?

Regex sed-如何获得段落的前两个句子?,regex,bash,command-line,sed,Regex,Bash,Command Line,Sed,假设我有一段话: Lorem Ipsum只是一个虚拟文本 印刷和排版业。 Lorem Ipsum一直是该行业的佼佼者 自 16世纪,一个不知名的印刷商 类型的厨房,并将其炒至 制作一本样书。它有 不仅存活了五个世纪,而且 同时,电子技术的飞跃 排版,基本上保留 不变。它在美国很流行 20世纪60年代随着Letraset的发布 含有Lorem Ipsum的纸张 段落,以及最近的 像Aldus这样的桌面发布软件 PageMaker,包括Lorem版本 Ipsum 使用sed,我如何获得一定数量的句子

假设我有一段话:

Lorem Ipsum只是一个虚拟文本 印刷和排版业。 Lorem Ipsum一直是该行业的佼佼者 自 16世纪,一个不知名的印刷商 类型的厨房,并将其炒至 制作一本样书。它有 不仅存活了五个世纪,而且 同时,电子技术的飞跃 排版,基本上保留 不变。它在美国很流行 20世纪60年代随着Letraset的发布 含有Lorem Ipsum的纸张 段落,以及最近的 像Aldus这样的桌面发布软件 PageMaker,包括Lorem版本 Ipsum

使用sed,我如何获得一定数量的句子,在本例中是两个句子,以句点分隔,并从给定段落中仅提取以下文本

Lorem Ipsum只是一个虚拟文本 印刷和排版业。 Lorem Ipsum一直是该行业的佼佼者 自 16世纪,一个不知名的印刷商 类型的厨房,并将其炒至 制作一本样书

说明:

\(
启动组

^
匹配行首

[^.]*
匹配任意数量的非句点字符

\。
匹配周期

[^.]*
匹配任意数量的非句点字符

\。
匹配周期

\)
终端组

\(
开始组
*$
匹配行末的所有内容
\)
结束组


\1
将整行替换为第一组。

编辑:针对某些更棘手的情况进行了更新

这在sed中很难做到,原因有很多!首先,
sed
使得我们很难处理文本中的标准多行段落。另一个原因是,
sed
并不是所有平台都标准化的,所以您永远不知道它将支持什么样的模式或选项。所以也许其他人可以帮你做这个部分

但是用Perl很容易做到这一点

use 5.10.0;
use strict;
use warnings;

my @texts = split /\R{2,}/, <<'END_OF_TEXT';
This is hard to do in sed for several reasons! First, sed makes it
hard to work on the standard multiline paragraphs we have in text.
Another reason is that sed is not standardized across all platforms,
so you never know what sorts of patterns or options it will support.
So perhaps someone else can help you with that part.

It was a dark and story night. Dr. Jones looked up
at the manor house with trepidation. Lightning
flashes could be seen both outside the house and
inside it, as St. Elmo's fire played across the lofty
spires. Mrs. Smith's fancy-dress party there on St. James's St.
was clearly going to be a lively one! Would anyone even notice
his mischief in time?  Dr. Jones chortled with glee as he scampered
up the step.
END_OF_TEXT


my $sentence_rx = qr{
    (?: (?<= ^ ) | (?<= \s ) )  # after start-of-string or whitespace
    \p{Lu}                      # capital letter
    .*?                         # a bunch of anything
    (?<= \S )                   # that ends in non-whitespace
    (?<! \b [DMS]r  )           # but isn't a common abbreviation
    (?<! \b Mrs )
    (?<! \b Sra )
    (?<! \b St  )
    [.?!]                       # followed by a sentence ender
    (?= $ | \s )                # in front of end-of-string or whitespace
}sx;

for my $paragraph (@texts) {
    say "NEW PARAGRAPH";
    say "Looking for each sentence.";

    my $count = 0;
    while ($paragraph =~ /($sentence_rx)/g) {
        printf "\tgot sentence %d: <%s>\n", ++$count, $1;
    }

    say "\nLooking for exactly two sentences.";

    if ($paragraph =~ / ^ ( (?: $sentence_rx \s*? ){2} ) /x) {
        say "\tgot two sentences: <<$1>>";
    }
    print "\n";
}
使用5.10.0;
严格使用;
使用警告;
my@text=split/\R{2,}/,,
运行时,将生成以下输出:

NEW PARAGRAPH
Looking for each sentence.
        got sentence 1: <This is hard to do in sed for several reasons!>
        got sentence 2: <First, sed makes it
hard to work on the standard multiline paragraphs we have in text.>
        got sentence 3: <Another reason is that sed is not standardized across all platforms,
so you never know what sorts of patterns or options it will support.>
        got sentence 4: <So perhaps someone else can help you with that part.>

Looking for exactly two sentences.
        got two sentences: <<This is hard to do in sed for several reasons! First, sed makes it
hard to work on the standard multiline paragraphs we have in text.>>

NEW PARAGRAPH
Looking for each sentence.
        got sentence 1: <It was a dark and story night.>
        got sentence 2: <Dr. Jones looked up 
at the manor house with trepidation.>
        got sentence 3: <Lightning
flashes could be seen both outside the house and
inside it, as St. Elmo's fire played across the lofty
spires.>
        got sentence 4: <Mrs. Smith's fancy-dress party there on St. James's St.
was clearly going to be a lively one!>
        got sentence 5: <Would anyone even notice
his mischief in time?>
        got sentence 6: <Dr. Jones chortled with glee as he scampered 
up the step.>

Looking for exactly two sentences.
        got two sentences: <<It was a dark and story night. Dr. Jones looked up 
at the manor house with trepidation.>>
新段落
寻找每个句子。
第一句:
第二句:
第三句:
第四句:
找两个句子。
有两句话:
新段落
寻找每个句子。
第一句:
第二句:

得到第3句:这将适用于您的示例:

sed 's/^\(\([^.]*\.\)\{2\}\).*/\1/'
或:


您可以使用
awk

 awk -vRS="." 'NR<=2' ORS="." file

awk-vRS=“.”NR这可能适合您:

 sed 's/\(\.[^.]*\.\).*/\1/' file
前提是每一段都在单独的一行

这可能适用于多个新行:

echo -e "a b c.\nx y z.\na b c" | sed ':a;$!N;/\(\.[^.]*\.\).*/!{$!ba};s//\1/;q'       
a b c.
x y z.

我想你很高兴你不会以“这是一个黑暗的故事之夜,琼斯博士惊恐地抬头看着庄园”这样的文字结尾,这种文字一次只在一行上起作用。当你走到这一行的末尾,在
“…已经”
时会发生什么?如何在
sed
中抓住下一行?您必须使用
sed
中的
N
命令获取下一个输入行。这就是
sed
难以使用的原因。这是太线为基础的,任何其他都是痛苦的。它还有太多需要转义的旧式BRE,并且不能保证您有高级正则表达式。另外,你不能在patterns.Hm中添加注释,那你为什么不把文件交给sed而把它放到patterns.Hm中呢?我假设每个段落都在一行。在示例中,+1很好地解释了这一点,但是一个小注释,您不需要在字符类中转义句点,因为字符类中唯一的元字符是^-和/啊,是的,它在其中一个中,但在另一个中不存在。我来清理一下。什么是sed-r?我的sed(1)手册页提供了此用法消息:
sed[-Ealn][e命令][f命令\文件][i扩展名][file…]
。这就是
sed
不可移植的问题。@tchrist问题不在于sed不可移植,而在于实现sed的某些人喜欢添加非标准选项。(注意,不要责怪sed,责怪gnu或bonzini)澄清一下,我不认为gnu sed实现新功能是错误的。但是,我认为文档中没有明确说明该选项是一个扩展,不能用于可移植的脚本是非常错误的。@tchrist:
sed-r
is
sed
,带有GNU-sed支持的扩展正则表达式。如果不支持,您必须使用没有
-r
和更多反斜杠的第一个版本。@William:for
sed
。也许应该有一种方法让所有这些东西都能提醒人们不可移植的选项。这是一个有趣的解决方案,但我认为还是太基于行了。任意点很难,不是吗?我试图在我的解决方案中防范它们,但是你的
詹姆斯先生会欺骗我,因为在点之前有一个非空白字符,然后是空白,然后是大写字母。这与句子边界是无法区分的,除非你让事情变得更加华丽。在NLP中很难得到100%的解决方案。是的,我同意这一点。我想我们不要看得太超前,因为OP还没有提供任何其他信息什么是NLP?互联网行话?ghostdog74:“互联网行话”?几乎没有!这是计算语言学领域中使用的一个非常标准的术语。根据维基百科:当文本处理遇到真实语言时,就有NLP了。@tchrist。啊,我明白了。我知道全称,但不知道缩写。thanks@ghostdog74:看来我已经暴露了我的日常职业,是吗?:)你可以把它打下一个,
\..[^.]*\.
可以是
\.[^.]*.
,因为下一个字符只能是一个真正的点。我宁愿逃跑
 sed 's/\(\.[^.]*\.\).*/\1/' file
echo -e "a b c.\nx y z.\na b c" | sed ':a;$!N;/\(\.[^.]*\.\).*/!{$!ba};s//\1/;q'       
a b c.
x y z.