FIND+PERL:如何对满是文件的目录中某个标签的所有情况添加一个连续的计数器

FIND+PERL: How to add a continuous counter to all cases of a certain tag in directory full of files

我有数千个 XML 文件,我需要为所有文件中每次出现的特定标记添加一个连续的增量计数器。换句话说,如果每个文件有 10 个文件和 50 个标签案例,则计数器应从 1 到 500,第一个文件为 1-50,第二个文件为 51-100,依此类推。

我正在使用 find 获取所有文件,并使用 Perl 在每个文件中执行搜索和替换操作。我正在使用的基本代码是这样的:

#!/bin/bash
find . -type f -name "*.xml" -exec perl -i -p0e "s#<tag>#<tag count=${COUNTER}>#gm" {} +`

这应该取每次出现的 <tag> 并添加当前计数器值,例如<tag counter=000001924>.

问题是我不知道如何维护文件之间的计数器值。如果我将 COUNTER=COUNTER+1 放在 find 之前,计数器显然不会递增。如果我把它放在 Perl 代码中,它会为每个文件重置为 0。

不幸的是,我能找到的所有答案都是将计数器编号添加到 文件名 而不是添加到 文件中的某些内容 ,这是一个不同的问题。

我该怎么做?

find -exec perl 可能会启动 perl 任意次,所以这不好。我们需要确保只有一个 perl 进程被启动(除非我们以某种方式将计数器存储在某个持久的地方,比如在文件中)。

我们可以 find 打印文件名并在 perl 中读取它们,但是这样做没有多大意义,因为在 Perl 中获取文件名列表同样容易。

#!/usr/bin/perl

use strict;
use warnings;

use File::Find::Rule qw( );
use XML::LibXML      qw( );

my $counter = 0;
my $parser = XML::LibXML->new();

for my $qfn (
   File::Find::Rule
      ->file
      ->name("*.xml")
      ->in(".")
) {
   eval {
      my $doc = $parser->parse_file($qfn);
      $_->setAttribute("count", ++$counter) for $doc->findnodes("//tag");
      $doc->toFile($qfn, 0);
      return 1;
   }
      or warn("Error processing \"$qfn\": $@\n");
}

您可以将其存储在一个您可以简单执行的文件中,或者您可以将其包装在 perl -e'...'.