0

我有一个包含大约 6000 个句子的文本文件,每个句子都有自己的一行。我想在 Windows 命令提示符下使用 Stanford Parser 来解析句子。但是,我需要一次向解析器发送一个句子(因为这些句子与另一个文件的句子对齐)。

我想编写一个 Perl 包装器:将输入文件中的一句话写入临时文件,将临时文件发送到解析器,解析一句话,将解析后的输出写入输出文件,然后将输出文件写入我的大输出文件 ParsedOutput.txt。

这可能是一件非常基本的事情,但我被困住了。任何帮助或指导将不胜感激。

谢谢!:)

编辑:这是我迄今为止尝试过的:

open (ENGDATA, "<1tot1660.txt");
open (ENGDATAOUT, ">temp.txt");
while (<ENGDATA>)
{
my $line = $_;
chomp $line;    
while ($line)
    {
    my @OneLine = $line;
    print ENGDATAOUT "$OneLine[0]\n";
    shift(@OneLine);
    }
}

我在想:将每一行作为数组中的一个元素,将第 0 个元素写入临时输出文件,然后删除第一个元素(这样就不会意外再次使用它)。我基本上被整个程序卡住了,但目前:在(一次)写一行到临时输出文件时。

编辑!(再次......谢谢,TLP 和 amon!:))这就是我最终所做的:

open (ENGDATA, "<Testing10.txt");
open (ENGDATAOUT, ">TempOut.txt");
open (PARSEDOUT, ">ParsedOutput.txt");

while (<ENGDATA>)    
{
    my $line = $_;
    chomp $line;
    my $inputfilename = $line;
    print ENGDATAOUT "$line\n";

    my $parsecommand = qx(java -mx150m -cp "*;" edu.stanford.nlp.parser.lexparser.LexicalizedParser -outputFormat "penn,typedDependencies" edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz $inputfilename);

    print PARSEDOUT "$parsecommand\n";
}

现在,我的输入中的每个单词都会出现此错误:

解析文件:上级 edu.stanford.nlp.process.DocumentPreprocessor:无法打开路径上级 解析文件:上级 [0 句]。

这是怎么回事?有谁知道,你能帮忙吗?谢谢!

4

2 回答 2

1

只是为了它,一个shell脚本版本。

while read -r; do
    printf '%s\n' "$REPLY" >tmp
    parser -input tmp -output tmp2
    cat tmp2
done <input >output
rm tmp tmp2

如果可以使解析器从标准输入读取并将结果写入标准输出,这可以大大简化。在 Linux上/dev/fd/0/dev/fd/1如果它坚持使用文件名参数,则可以使用。

printf '%s\n' "$REPLY" |
parser -input /dev/fd/0 -output /dev/fd/1

并完全取消临时文件。

于 2012-08-18T19:48:18.147 回答
0

好的。您的代码似乎正在将文件复制1tot1160.txttemp.txt,在此过程中引入了一些非常有趣的语法;-)

我会这样做:

  1. 在一处声明所有文件名:

    #!/usr/bin/perl
    use strict; use warnings;
    my $BigInFile     = ...;
    my $BigOutFile    = ...;
    my $ParserInFile  = ...;
    my $ParserOutFile = ...;
    
  2. 打开大文件,然后开始循环输入:

    open my $BigIn,  '<', $BigInFile  or die "Cant open $BigInFile";
    open my $BigOut, '>', $BigOutFile or die "Cant open $BigOutFile";
    while (defined(my $line = <$BigIn>)) {
        print $BigOut doStanford($line);
    }
    

    我们将大输入文件的每一行放入$line定义时(阅读:当我们没有 EOF 时)。然后我们将子例程的输出打印doStanford到大输出文件,假设它已经有一个结束换行符。如果没有,请随意编写代码来附加它。

  3. 编写子程序doStanford。我们取一行,将其写入 Temp 文件,调用程序,然后读取另一个 Temp 文件并返回内容:

    sub doStanford {
        my ($line) = @_; # unpack arguments
    
        # open the firstfile:
        open my $StanfordIn, '>', $ParserInFile
          or die "Couldn't open $ParserInFile";
        print $StanfordIn $line; # already has newline
        close $StanfordIn;
    
        # do the call to the parser. I don't know the interface
        # so I assume it is "parser --in INFILE --out OUTFILE"
        my $returnValue = system("parser",
          "--in", $ParserInFile,
          "--out", $ParserOutFile);
        if ($returnValue != 0) {
            # an error occured
            die "The Parser exited with return value $?: $!.\n";
        }
    
        # read in the other file, and return:
        open my $StanfordOut, '<', $ParserOutFile
          or die "Couldn't open $ParserOutFile";
        my $parsed = <$StanfordOut>; # we only want the first line
        return $parsed;
        # implicit close $StanfordOut
    }
    

可能有;-)这里有一些错别字,所以最好自己写。

system我为良好风格的呼吁做了一些错误处理。退出值 0 表示成功,非零退出值(尤其是 -1)表示某些错误或异常终止。

如果 Parser 可以输出到 STDOUT 而不是文件,则可以执行里面的命令qx{}

my $parsed = qx{parser --in INFILE};

这样我们就不能进行错误处理,但我们不需要额外的文件。

system调用内部,我将参数拆分为一个列表。如果我们只提供一个字符串,命令行会在每个空格处拆分它;如果我们的路径名也包含空格,则不可取。我这样做的方式,他们是安全的。

如果您可以为此使用模块,请使用该模块。它更安全,更容易。

编辑

  • 的返回值system实际上并不是被调用命令的退出状态。命令成功时返回值仅为 0,错误时返回 true。退出状态是表达式的值$? >> 8$!可能是有原因的。
于 2012-08-18T12:38:27.120 回答