【问题标题】:How to remove lowercase sentence fragments from text?如何从文本中删除小写句子片段?
【发布时间】:2011-01-27 06:04:05
【问题描述】:

我很想使用正则表达式或简单的 Perl oneliner 从标准文本文件中删除小写句子片段。

这些通常被称为语音或归属标签,例如 - 他说,她说等。

这个例子展示了使用手动删除之前和之后:

  1. 原文:

“啊,完全正确!”阿辽沙叫道。

“哦,别再装傻了!一些白痴进来了,你把我们 丢人!”窗边的女孩叫道,突然转向她的父亲。 带着轻蔑和轻蔑的神情。

“等一下,瓦尔瓦拉!”父亲喊道,说话专横,但 相当赞许地看着他们。 “这就是她的性格,”他说, 再次向阿辽沙讲话。

“你去哪儿了?”他问他。

“我想,”他说,“我忘记了什么……我的手帕,我 想想....好吧,即使我什么都没忘记,让我留在 小。”

他坐了下来。父亲站在他身边。

“你也坐下,”他说。


  1. 手动删除所有小写句子片段:

“啊,完全正确!”

“哦,别再装傻了!一些白痴进来了,你把我们 丢人!”

“等一下,瓦尔瓦拉!” “这就是她的性格,”

“你去哪儿了?”

“我想,”“我忘记了什么……我的手帕,我 想想....好吧,即使我什么都没忘记,让我留在 小。”

他坐了下来。父亲站在他身边。

“你也坐下”


我已将直引号“更改为平衡并尝试过:” (...)+[.]

当然,这会删除一些片段,但会删除一些平衡引号中的文本和以大写字母开头的文本。 [^A-Z] 在上述表达式中不起作用。

我意识到可能无法达到 100% 的准确率,但任何有用的表达式、perl 或 python 脚本将不胜感激。

干杯,

亚伦

【问题讨论】:

  • 如果不是“父亲站在他身边”,你会怎么做。句子是“父亲站在吉姆身边。”?
  • 我认为您需要更清楚地定义“小写句子片段”是什么。特别是,为什么是“惊呼阿辽沙”。一个小写的句子片段,但“父亲站在他身边”。不是吗?
  • 我认为“小写句子片段”的意思是“信号短语”nutsandbolts.washcoll.edu/quoting.html#signal

标签: python regex perl awk


【解决方案1】:

这是一个应该做的 Python sn-p:

 thetext="""triple quoted paste of your sample text"""
 y=thetext.split('\n')
 for line in y:
    m=re.findall('(".*?")',line)
    if m:
        print ' '.join(m)
    else:
        print line

【讨论】:

    【解决方案2】:

    我不完全确定您使用的是哪个编辑器,如果您使用的是支持原子分组的编辑器(例如 EditorPad Pro),您可以使用下面的正则表达式进行搜索和替换:

    搜索

    (".+?"|^[A-Z].+\r\n)(.(?!"))* 
    Note: you should replace \r\n with \n or \r according to your line breaks
    

    替换为

    \1
    

    下面是对正则表达式的一点解释:

    第一个捕获组用于引号和以大写字母开头的行之间的字符。第二个捕获组用于在引号之后但在另一个引号之前的任何字符。

    【讨论】:

    • 我在那个正则表达式中看不到任何原子组——只有两个捕获组和一个负前瞻。
    【解决方案3】:

    这适用于问题中显示的所有情况:

    sed -n '/"/!{p;b}; s/\(.*\)"[^"]*/\1" /;s/\(.*"\)\([^"]*\)\(".*"\)/\1 \3/;p' textfile
    

    在以下情况下会失败:

    He said, "It doesn't always work."
    
    "Secondly," I said, "it fails for three quoted phrases..." He completed my thought, "with two unquoted ones."
    
    I replied, "That's right." dejectedly.
    

    【讨论】:

      【解决方案4】:

      如果我明白你在追求什么...通过这样的正则表达式传递每一行应该可以...

      您可以使用 perl 调试器来解决这个问题。只需在 linux/mac 的命令行中输入 perl -de 42 即可进入 perl 调试器。 (“42”只是一个有效的表达方式——它可以是任何东西,但为什么不选择生命的意义呢?)

      无论如何

      open FILE, "<", "filename.txt" or die $!;
      while (my $line = <FILE>) {
         @fixed_text = $line =~ m{(?:(" .+? ")) | (?:\A .* [^"] .* \z)}xmsg;
        for my $new_line (@fixed_text) {
          print qq($new_line );
        }
        print qq(\n);
      }
      

      注意:抱歉,我不得不对其进行编辑 - 根本没有看到您想要没有任何引号的行...

      是的,Regex 和 Perl 很棒。它应该 100% 准确并获取所有实例,接受跨段落引用的情况

      【讨论】:

        【解决方案5】:

        Text::Balanced 模块是您想要使用 Perl 时所追求的。以下内容应该能够提取您示例中所有引用的语音(不漂亮,但可以完成工作)。

        它也适用于 Dennis 的测试用例。

        下面代码的优点是引号按段落分组,对后面的分析可能有用也可能没用

        脚本

        use strict;
        use warnings;
        use Text::Balanced qw/extract_quotelike extract_multiple/;
        
        my %quotedSpeech;
        
        {
            local $/ = '';
            while (my $text = <DATA>) { # one paragraph at a time
        
                while (my $speech = extract_multiple(
                                    $text,
                                    [sub{extract_quotelike($_[0])},],
                                    undef,
                                    1))
                {   push @{$quotedSpeech{$.}}, $speech; }
            }
        }
        
        # Print total number of paragraphs in DATA filehandle
        
        print "Total paragraphs: ", (sort {$a <=> $b} keys %quotedSpeech)[-1];
        
        # Print quotes grouped by paragraph:
        
        foreach my $paraNumber (sort {$a <=> $b} keys %quotedSpeech) {
            print "\n\nPara ",$paraNumber;
            foreach my $speech (@{$quotedSpeech{$paraNumber}}) {
                print "\t",$speech,"\n";
            }
        }
        # How many quotes in paragraph 8?
        print "Number of quotes in Paragraph 8: ", scalar @{$quotedSpeech{8}};
        

        __DATA__

        “啊,完全正确!”阿辽沙叫道。

        “哦,别再装傻了! 一些白痴进来了,你让我们去 可耻!”窗边的女孩叫道, 突然转向她的父亲 轻蔑轻蔑的神气。

        “等一下,瓦尔瓦拉!”她哭了 父亲,说话专横,但是 相当赞许地看着他们。 “这就是她的性格,”他说, 再次向阿辽沙讲话。

        “你去哪儿了?”他问他。

        “我想,”他说,“我忘记了 东西……我的手帕,我 想想....好吧,即使我没有 什么都忘了,让我留个 小。”

        他坐了下来。父亲站在他身边。

        “你也坐下,”他说。

        他说,“它并不总是有效。”

        “其次,”我说,“它失败了 三个引用的短语……”他完成了 我的想法是,“有两个未引用的。”

        我回答说:“没错。”垂头丧气。

        输出

        Total paragraphs: 10
        
        Para 1  "Ah, that's perfectly true!"
        
        
        Para 2  "Oh, do leave off playing the fool! Some idiot comes in, and you put us
        to shame!"
        
        
        Para 3  "Wait a little, Varvara!"
                "That's her character,"
        
        
        Para 4  "Where have you been?"
        
        
        Para 5  "I think,"
                "I've forgotten something... my handkerchief, I think.... Well, even if
        I've not forgotten anything, let me stay a little."
        
        
        Para 7  "You sit down, too,"
        
        
        Para 8  "It doesn't always work."
        
        
        Para 9  "Secondly,"
                "it fails for three quoted phrases..."
                "with two unquoted ones."
        
        
        Para 10 "That's right."
        

        【讨论】:

        • perl script.pl textfile 不产生任何输出。
        • @Dennis:那是因为您需要以 perl script.pl "text" 的身份运行脚本,并按照现在的方式编写。
        • @Dennis:查看更新后的代码,它也适用于您的失败案例。
        • 您的新版本更好,但它会在多短语输入的各个部分之间打印换行符(例如,以“Wait”和“Secondly”开头的部分)。
        • @Dennis:这不是问题;它只是格式化。我会尽可能发布。
        猜你喜欢
        • 2012-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 2012-04-03
        • 1970-01-01
        • 2014-11-10
        相关资源
        最近更新 更多