【问题标题】:Replacing text in a file from a list in another file?从另一个文件的列表中替换文件中的文本?
【发布时间】:2013-05-19 17:49:00
【问题描述】:

I asked this question before 但不要认为我真的根据给出的答案正确解释了它。

我有一个名为 backup.xml 的文件,它有 28,000 行,其中包含短语 *** 766 次。我还有一个名为 list.txt 的文件,其中有 766 行,每行都有不同的关键字。

我基本上需要做的是将list.txt 中的每一行插入backup.xml 以替换提到的*** 的766 个位置。

这是list.txt 中包含的内容的示例:

Anaheim
Anchorage
Ann Arbor
Antioch
Apple Valley
Appleton

这是backup.xml 中包含*** 的行之一的示例:

<title>*** Hosting Services - Company Review</title>

因此,例如,提到*** 的第一行应该根据上面的示例更改为:

<title>Anaheim Hosting Services - Company Review</title>

任何帮助将不胜感激。提前致谢!

【问题讨论】:

  • 输入和所需输出的任何示例?
  • 刚刚为您更新了问题。
  • 我先看到了上一个问题。我的回答是合适的。

标签: perl shell command-line command


【解决方案1】:

在这种情况下,您可能可以将 XML 视为纯文本。 所以读取 XML 文件,并用从关键字文件中读取的行替换每个出现的标记:

#!/usr/bin/perl

use strict;
use warnings;

use autodie qw( open);

my $xml_file  = 'backup.xml';
my $list_file = 'list.txt';
my $out_file  = 'out.xml';  

my $pattern='***';

# I assumed all files are utf8 encoded
open( my $xml,  '<:utf8', $xml_file  );
open( my $list, '<:utf8', $list_file );
open( my $out,  '>:utf8', $out_file  );

while( <$xml>)
  { s{\Q$pattern\E}{my $kw= <$list>; chomp $kw; $kw}eg;
    print {$out} $_;
  }

rename $out_file, $xml_file;

【讨论】:

  • print {$out} $_;为什么要大括号
  • 它确保$out 被用作文件句柄。它们在这里不是必需的,但无论如何我都会使用它们,因为我发现它让读者更清楚print 是指向$out
【解决方案2】:

这个怎么样:

awk '{print NR-1 ",/\\*\\*\\*/{s/\\*\\*\\*/" $0 "/}"}' list.txt > list.sed
sed -f list.sed backup.xml

第一行使用awk根据列表创建一个搜索/替换命令列表,然后通过sed在下一行执行。

【讨论】:

    【解决方案3】:

    使用awk。它读取backup.xml 文件,当找到*** 文本时,我从list.txt 文件中提取一个单词。 BEGIN 块从参数列表中删除 list.txt 以避免对其进行处理。参数的顺序非常重要。另外我假设每行只有一个*** 字符串。

    awk '
            BEGIN { listfile = ARGV[2]; --ARGC }
            /\*\*\*/ {
                    getline word <listfile
                    sub( /\*\*\*/, word )
            }
            1     ## same as { print }
    ' backup.xml list.txt
    

    【讨论】:

      【解决方案4】:

      如果这两个文件顺序对应,你可以使用paste命令将两个文件中的行连接起来,然后进行后处理。

      paste list.txt backup.xml | 
      awk 'BEGIN {FS="\t"} {sub(/\*\*\*/, $1); print substr($0, length($1)+2)}'
      

      粘贴命令将产生以下内容:

      Anaheim \t <title>*** Hosting Services - Company Review</title>
      

      而 AWK 中的单行将 *** 替换为第一个字段,随后删除第一个字段和其后的字段分隔符 (\t)。

      另一种变化是:

      paste list.txt backup.xml | 
      awk 'BEGIN {FS="\t"} {sub(/\*\*\*/, $1); print $0}' | 
      cut -f 2-
      

      【讨论】:

      • 从问题来看,你不能假设两个文件的行数相同,所以粘贴不起作用。
      • 这就是为什么我从 'if' 语句开始
      猜你喜欢
      • 2019-03-06
      • 2018-03-29
      • 1970-01-01
      • 2018-12-27
      • 2016-07-12
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2012-04-13
      相关资源
      最近更新 更多