修改Perl脚本以每20个字输出一行

时间:2011-11-28 18:03:12

标签: perl text-processing

我正在使用开源perl脚本来创建基于英语wikipedia转储的文本语料库。已经提取了纯文本,但是仍然需要删除各种标点符号等。但是,此脚本的输出实际上创建了一个包含单行的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'([\w\s]+[\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日找到   公元前一世纪,在道家哲学家老子的作品中,以及后来的作品   几个世纪的庄子和包景燕。首先是“无政府主义者”一词   在英国内战期间,1642年进入英语   一个滥用的术语,由保皇党人使用,反对他们的Roundhead对手。   到法国大革命时,有些人,比如恩拉格斯,开始了   积极使用这个词,与雅各宾集中化相对立   权力,将“革命政府”视为矛盾。由   在19世纪之交,英语单词“无政府主义”已经失去了它   最初的负面含义。现代无政府主义源于世俗化   或启蒙运动的宗教思想,尤其是让 - 雅克   卢梭关于自由道德中心性的论证。无政府主义”,   Encarta Online Encyclopedia 2006(英国版)。从这种气候   William Godwin开发了许多人认为的第一个表达方式   现代无政府主义思想。根据Peter Kropotkin的说法,Godwin是   “第一个制定政治和经济概念的人   无政府主义,即使他没有给出这个想法的名字   在他的作品中发展了“,而戈德温将他的无政府主义思想与他联系起来   早期的埃德蒙伯克。无政府共产主义者约瑟夫·德雅克就是这样   第一个形容自己是“自由主义者”的人。与蒲鲁东不同,他   他认为,“这不是他或她的劳动的产物   工人有权,但满足他或她的需要,   无论什么可能是自然的。耶稣有时被认为是第一个   基督教无政府主义传统中的无政府主义者。 Georges Lechartier   写道:“无政府状态的真正创始人是耶稣基督和   欧洲,在1848年的革命之后发生了严厉的反应   十个国家经历了短暂或长期的社会动荡   团体进行民族起义。经过大部分这些   系统变革的尝试以失败告终,保守元素   利用分裂的社会主义者群体,无政府主义者,   自由主义者和国家主义者,以防止进一步的反抗。布朗基主义者,   Philadelphes,英国工会会员,社会主义者和社会   民主党人。由于它与活跃的工人运动的联系,   国际成为一个重要的组织。卡尔马克思成了一个   国际领导人物及其将军成员   委员会。蒲鲁东的追随者,共产主义者,反对马克思的国家   社会主义,主张政治弃权和小财产   增持。在1868年,他们参加了不成功的   和平与自由联盟(LPF),俄罗斯革命家米哈伊尔   巴枯宁和他的集体主义无政府主义者协会加入了第一   国际(已决定不参与LPF)。在   首先,集体主义者与马克思主义者合作推动了第一次   国际社会更加革命的社会主义方向。   随后,国际两极分化为两个阵营   马克思和巴枯宁各自的傀儡。在1872年,   冲突达到高潮,两组之间最终分裂   海牙国会,巴枯宁和詹姆斯纪尧姆被驱逐出境   国际及其总部已转移到纽约。   作为回应,联邦主义部门组建了自己的国际组织   圣伊米尔大会采用革命无政府主义计划。   Black Rose Books 2005)ISBN 1-55164-251-4。

文件中有7个值得发短信的文字。因此,使用列表或其他数据结构可能对这些要求有点过分。

为了满足我的要求需要什么?

5 个答案:

答案 0 :(得分:6)

考虑使用Text::WrapText::Autoformat等内容。

答案 1 :(得分:1)

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; 

答案 2 :(得分:0)

在不知道有关此问题的更多细节的情况下,我建议使用强力解决方案: 啜饮整个入口, 拆分为基于“”的数组, foreach数组并在每20个元素后打印“\ n”。

答案 3 :(得分:0)

对于Perl来说,有多种方法可以解决这个问题,但是一种(反常的?!)方法是逐字节而不是逐行读取文件,或者将整个事情搞砸。它相当粗野force-ish但是它有效。从本质上讲,你正在交换磁盘使用的内存使用。

#!/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);

答案 4 :(得分:0)

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

$/ = ' ';

然后通过 word 循环输入

while (<>) {

修剪

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

如果它是所有空格,请跳过它:

    $_ or next;

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

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

    push @words, split /\s+/; 

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

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

然后打印剩余的东西:

print "@words\n" if @words;