修改Perl脚本,使其每20个单词输出一个新行



我使用一个开源perl脚本来创建一个基于英语维基百科转储的文本语料库。纯文本已被提取,但各种标点符号等仍然需要删除。但是,该脚本的输出实际上创建了一个包含单行的7.2GiB文本文件。由于我的需要,我想改变脚本,使它每20个单词插入一个新的行字符。

到目前为止,我已经试过了:

$wordCount=0;
while (<STDIN>) {
  $wordCount++;
  //text processing regex commands here

  # Remove ellipses 
  s/.../ /g;
  # Remove dashes surrounded by spaces (e.g. phrase - phrase)
  s/s-+s/ /g;
  # Remove dashes between words with no spaces (e.g. word--word)
  s/([A-Za-z0-9])--([A-Za-z0-9])/$1 $2/g;
  # Remove dash at a word end (e.g. three- to five-year)
  s/(w)-s/$1 /g;
  # Remove some punctuation
  s/(["�,;:%�?�!()[]{}<>_.])/ /g;
  # Remove trailing space
  s/ $//;
  # Remove double single-quotes 
  s/'' / /g;
  s/ ''/ /g;
  # Replace accented e with normal e for consistency with the CMU pronunciation dictionary
  s/�/e/g;
  # Remove single quotes used as quotation marks (e.g. some 'phrase in quotes')
  s/s'([ws]+[w])'s/ $1 /g;
  # Remove double spaces
  s/  / /g;

  chomp($_);
  if ($wordCount == 20){
    print uc($_) . "n";
    $wordCount=0;
  }
  print uc($_) . " ";
}
print "n";

然而,这似乎不起作用,因为原始输出只有随意分散的换行符。我想对文本进行格式化,使其适合典型的1200px宽的显示器,没有换行。

文件中的一个示例输入文本是

简明牛津政治词典。无政府主义的支持者(被称为"无政府主义者")提倡无国家社会是唯一道德的社会组织形式。有许多类型和传统无政府主义,并不是所有的都是相互排斥的。无政府主义社会运动的受欢迎程度经常出现波动。的"无政府主义"一词源于希腊语ναρχος, anarchos,意为"无政府主义"没有统治者",它作为同义词的使用在国外仍然很常见美国。最早的无政府主义主题出现在公元6世纪在公元前100年,道教哲学家老子的作品,并在后来几个世纪以来庄子和包景炎的作品。首先是"无政府主义者"这个词在1642年英国内战期间进入英语,作为这是保皇党人对圆颅党对手的蔑称。到了法国大革命时期,开始了一些运动,比如enrag运动积极地使用这个词,反对雅各宾集权把"革命政府"看作是自相矛盾的。由19世纪之交,英语单词"无政府主义"失去了它的意义最初的负面含义。现代无政府主义起源于世俗或者启蒙运动的宗教思想,尤其是让-雅克卢梭关于自由的道德中心的论证。无政府主义",网上百科全书2006(英国版)。在这种气候下威廉·戈德温发明了许多人认为的第一个表达现代无政府主义思想。根据彼得·克鲁泡特金的说法,戈德温是第一个提出政治和经济概念的人无政府主义,尽管他并没有给这种思想起这个名字而戈德温则把他的无政府主义思想附加在他的作品中早期的埃德蒙·伯克无政府共产主义者约瑟夫·达姆贾克是第一个自称"自由主义者"的人。不像蒲鲁东,他认为,这不是他或她的劳动成果工人有权利,但要满足他或她的需要,不管他们的本性如何。耶稣有时被认为是第一个基督教无政府主义传统中的无政府主义者。乔治Lechartier他写道:"无政府状态的真正创始人是耶稣基督。在在欧洲,1848年革命后的激烈反应,在此期间10个国家经历了短期或长期的社会动荡一些团体发动了民族起义。在这之后系统变革的尝试以失败告终,保守分子利用社会主义者,无政府主义者,自由主义者和民族主义者,以防止进一步的反抗。Blanquists,费城,英国工会会员,社会主义者和社会主义者民主党人。由于它与活跃的工人运动有联系国际成为了一个重要的组织。卡尔·马克思成为了他是国际的领导人物,也是国际总委员会的成员理事会。蒲鲁东的追随者,互惠主义者,反对马克思的国家论社会主义,主张政治上的禁欲主义和小财产主义资产。1868年,在他们未能成功参加和平与自由联盟(LPF),俄国革命家米哈伊尔巴枯宁和他的集体主义无政府主义伙伴们加入了第一阵营国际(已经决定不参与LPF)。在首先,集体主义者和马克思主义者共同推动了第一种思想国际社会向更革命的社会主义方向发展。随后,国际分化为两个阵营,与马克思和巴枯宁作为他们各自的名义领袖。1872年冲突以两派在会议上的最终决裂而达到高潮海牙会议,巴枯宁和詹姆斯·纪尧姆被驱逐出境国际组织及其总部迁至纽约。作为回应,联邦制派成立了他们自己的国际圣伊米尔代表大会通过了一项革命的无政府主义纲领。黑玫瑰图书2005)ISBN 1-55164-251-4.

文件中有大约7 gb的文本。因此,对于这些要求,使用列表或其他数据结构可能有点矫枉过正。

需要什么来满足我的要求?

考虑使用Text::Wrap或Text::Autoformat

open my $in, '<', $inFileName; 
open my $out, '>', $outFileName; 
my $wordcount = 0; 
while(defined( my $line = <$in> )){ 
  $line=~s/n//g; #remove newline character
  #split the words into an array(could use 'W+' instead of ' ')
  my @words = split ' ', $line; 
  foreach my $word (@words){ 
    $wordCount++; 
    if ($wordCount == 20){ 
      $wordCount = 0; 
      print $out "n"; 
    }
    else {
      print $out uc($word)." ";
    }
  } # end of foreach line in input 
} # end of file while loop 
close $in; 
close $out; 

首先,将perl的输入记录分隔符设置为常用且有用的分隔符,如空格:

$/ = ' ';

然后通过word:

对输入word进行循环
while (<>) {

修改:

    s/^s+|s+$//g;

如果全是空格则跳过:

    $_ or next;

执行您需要的任何其他转换

,然后将其添加到堆栈中,拆分任何内部制表符或其他类似空格的字符:

    push @words, split /s+/; 

接下来,检查你是否有20个单词,如果有,打印出来:

    print join(' ' => splice @words, 0, 20), "n" while @words >= 20;
}

然后打印剩余的内容:

print "@wordsn" if @words;

在不了解更多关于这个问题的细节的情况下,我建议使用蛮力解决方案:吞下整个入口,拆分为基于" "的数组,读取数组,每20个元素后输出"n"。

对于Perl来说,有多种方法可以解决这个问题,但是有一种(不正常的?!)方法是一个字节一个字节地读取文件,而不是一行一行地读取,或者将整个文件读入。这有点像蛮力,但确实有效。从本质上讲,您是在用内存使用交换磁盘使用。

#!/usr/bin/perl -w
use strict;
open(IN, "in.txt") or die;
my $rc = 1;
my $wc = 0;
my $new;
while ($rc != 0)
{
  # Read a byte - not safe for Unicode or other double-byte environments!
  $rc = read IN, $new, 1, 0;
  # We're only interested if the byte isn't punctuation (POSIX character class).
  if ($new !~ m/[[:punct:]]/)
  {
    # word boundary?
    if ($new =~ m/ /)
    {
      $wc++;
      if ($wc % 20 == 0)
      {
        print "n";  # 20th word, time for a new line.
      }
    }
    print $new;
  }
  # move on to the next byte
  seek IN, 0, 1;
}
close(IN);

最新更新