Regex 提取短语后的所有文本,然后在每行开头添加文件名?

Regex 提取短语后的所有文本,然后在每行开头添加文件名?,regex,perl,sed,Regex,Perl,Sed,我正在做一个有3k个文本文档的文献计量学项目,我试图找出如何从非结构化文本到引用列表。格式变化很大,但都以引用的作品结尾。到目前为止,我已经想到了这个: sed -n '/Works Cited/,$p' Jones.txt > newfile.txt 在所有~3k文档上运行之后,我将合并它们进行分析。但知道哪一行/引用来自哪一份文件是有意义的。因此,我最好的猜测是,这将涉及两个步骤: 摘录引用的短语“作品”后面的行 在每行的开头插入文件名。(没有标准的元数据结构,甚至没有出现作者、标题

我正在做一个有3k个文本文档的文献计量学项目,我试图找出如何从非结构化文本到引用列表。格式变化很大,但都以引用的作品结尾。到目前为止,我已经想到了这个:

sed -n '/Works Cited/,$p' Jones.txt > newfile.txt
在所有~3k文档上运行之后,我将合并它们进行分析。但知道哪一行/引用来自哪一份文件是有意义的。因此,我最好的猜测是,这将涉及两个步骤:

  • 摘录引用的短语“作品”后面的行
  • 在每行的开头插入文件名。(没有标准的元数据结构,甚至没有出现作者、标题等的一致行。)
  • 例如,对于名为Jones.txt的文档:

    …弗林蒂利亚·达皮布斯·帕特万岁。不需要马蒂斯·奥奇(mattis orci)、奥纳雷(vitae ornare)和泰勒斯(tellus)。自由门的Nunc。CRA非同侧id仅适用于拍卖人ullamcorper。Lorem>ipsum dolor sit amet,奉献精英。Phasellus nec nulla tincidunt,>威尼斯人nisi a,pharetra neque。Morbi euismod id mauris vitae酒店。Nam>sagittis mattis urna vel concertetur。整型菱形狮子座在矢状位>sollicitudin

    引用作品

    琼斯,特德。生物学。纽约:企鹅,2009年

    史密斯,玛丽。《蝴蝶与生物学》杂志21.2(2013):1-10

    我想制作这个:

    琼斯,琼斯,特德。生物学。纽约:企鹅,2009年

    琼斯,史密斯,玛丽。《蝴蝶与生物学》杂志21.2(2013):1-10

    这可能吗?有没有更好的方法来考虑这个问题?我试着在某处和其他地方寻找解决方案,但也许我没有找到合适的短语。这在sed、perl等中是最好的吗?解决方案是否会更改为运行*.txt而不仅仅是Jones.txt

    我们将非常感谢您的任何帮助

    -JCC

    使用GNU
    awk
    您没有提到您的操作系统,但假设您可以访问GNU
    awk
    ,请尝试:

    $ awk 'FNR==1{f=0} f && /./{printf "%s, ", FILENAME} f{print} /Works Cited/{f=1}' *.txt
    
    Jones.txt, Jones, Ted. Biology. New York: Penguin, 2009.
    
    Jones.txt, Smith, Mary. "Butterflies and Biology." Journal 21.2 (2013): 1-10.
    
    for f in *.txt
    do
        sed -n '/Works Cited/,${/Works Cited/d; /./ s/^/'"$f, /;p}" "$f"
    done
    
    注意,在这个解决方案中,您可以通过上述示例中的
    *.txt
    在命令行上一次指定所有文件名,GNU
    awk
    在变量
    FILENAME
    从一个文件切换到下一个文件时更新该变量

    工作原理:

    • FNR==1{f=0}

      在每个文件的第一行,将flag
      f
      设置为零,表示我们尚未看到该文件引用的
      作品

    • f&&/{printf“%s”,FILENAME}

      如果标志
      f
      非零(意思是已经看到
      引用的作品
      ),并且如果行非空(行上至少有一个字符),则打印文件名,后跟逗号和空格

    • f{print}

      如果标志
      f
      非零,则打印整行

    • /引用作品/{f=1}

      如果此行包含引用的
      作品
      ,则将标志
      f
      设置为一

    FILENAME
    变量是GNU扩展名

    非GNU
    awk
    对于不支持
    FILENAME
    awk
    版本,我们可以使用shell循环,依次将
    awk
    变量
    name
    设置为每个文件的名称:

    for f in *.txt
    do 
        awk -v name="$f" 'f && /./{printf name ", "} f{print} /Works Cited/{f=1}' "$f"
    done
    
    使用
    sed
    如果确实必须使用
    sed
    ,请尝试:

    $ awk 'FNR==1{f=0} f && /./{printf "%s, ", FILENAME} f{print} /Works Cited/{f=1}' *.txt
    
    Jones.txt, Jones, Ted. Biology. New York: Penguin, 2009.
    
    Jones.txt, Smith, Mary. "Butterflies and Biology." Journal 21.2 (2013): 1-10.
    
    for f in *.txt
    do
        sed -n '/Works Cited/,${/Works Cited/d; /./ s/^/'"$f, /;p}" "$f"
    done
    

    如果您确信您的文件名不包含任何sed活动字符,那么这种方法是可以接受的。

    您可以通过一个简单的perl脚本一步完成这一点

    基本用法:

    extract.pl myoutfile.txt
    
    以下是脚本:

    #!/usr/bin/env perl
    use strict 'vars';
    use warnings;
    use feature qw/say/;
    
    my $outfile   = $ARGV[0] || 'citations.out';
    my $split_on  = $ARGV[1] || 'Works Cited';
    my $filetypes = $ARGV[2] || 'txt';
    
    # Open Outfile
    open(my $fh_outfile, '>', $outfile) 
      or die "Could not open file '$outfile' $!";
    
    # Get list of files
    my @files = <*.$filetypes>;
    my $count = scalar @files;
    my $current = 0;
    
    # Scan files
    foreach my $file (@files) {
      say "\nWorking on: $file [ " . ++$current  .  " / $count ]";
    
      # Read in the file contents
      my @contents = do {
        open my $fh, "<", $file
            or die "Could not open $file $!";
        <$fh>;
      };
    
      my $split_found = 0;
      foreach my $line ( @contents ) {
        # Write to output file, only when in
        # works cited section, and line isn't empty
        if ( $split_found && $line =~ m/\w/ ) {
          print $fh_outfile "$file, $line";
          print "   >$file, $line";
        }
    
        # Flag 'Works Cited' section
        $split_found = $split_found || $line =~ m/^$split_on\s*$/g;
      }
    };
    
    close $fh_outfile;
    
    #/usr/bin/env perl
    使用严格的“变量”;
    使用警告;
    使用功能qw/say/;
    我的$outfile=$ARGV[0]| |'引文.out';
    我的$split_on=$ARGV[1]| |“引用的作品”;
    my$filetypes=$ARGV[2]||“txt”;
    #开放式出铁口
    打开(我的$fh_输出文件,'>',$outfile)
    或“无法打开文件“$outfile”$!”;
    #获取文件列表
    我的@files=;
    我的$count=标量@文件;
    我的$current=0;
    #扫描文件
    foreach my$文件(@files){
    说“\n处理:$file[”++$current./$count]”;
    #读入文件内容
    我的@contents=do{
    打开我的$fh,“$file,$line”;
    }
    #国旗‘引用作品’组
    $split_found=$split_found | |$line=~m/^$split_on\s*$/g;
    }
    };
    关闭$fh_输出文件;
    
    是否有任何东西显示引用作品的结尾?或者任何显示下一篇文章开头的内容?如果没有,你需要给出更多被引用作品的例子,这样就可以导出模式。每个被引用的作品都在以句号结尾的单独一行上,但是每个文本都在一个单独的文件中,所以我不知道这是否有区别。使用
    ms
    标志,它会让你在一个组中引用所有的作品,然后运行另一个正则表达式来拆分这些作品。回答得很好。注意:假设(对于sed)文件名(
    \&
    )中没有通常情况下的特殊字符。