使用文本文件中的列表查找和替换?

时间:2013-05-24 05:03:28

标签: perl shell command-line command

我甚至不确定这是否可行,但我确信这是可能的。

我在文件backup.xml中有这行766次:

*** Hosting Services

然后我有文件list.txt,其中包含766行。我需要将***替换为list.txt中每条766行的内容 - 如果可能的话,它必须按相同的顺序排列。

提前感谢您的帮助!

4 个答案:

答案 0 :(得分:1)

<强>观

loop over the lines of the B(ackup file)
  if you (F)ind a B-line to change
     read the next line of the L(ist file)
     change
  print the line to R(result file)

<强>安排:

read_open B
read_open L
write_open R
while (line from B)
  if (F) {
    read replacemment from L
    change line
  }
  print line to R
}
close R, L, B

实施I(read_open,循环,看看B):

use strict;
use warnings;
use English qw(-no_match_vars);

my $bfn = '../data/AA-backup-xml';
open my $bfh, '<', $bfn or die "Can't read open '$bfn': $OS_ERROR";
while (my $line = <$bfh>) {
        print $line;
}
close $bfh or die "Can't read close '$bfn': $OS_ERROR";

输出:

perl 01.pl
whatever
whatever
*** Hosting Services
whatever
whatever
whatever
*** Hosting Services
whatever
whatever
*** Hosting Services
whatever
whatever
whatever
*** Hosting Services

实施II(读/写,F,替换,第一个结果):

use Modern::Perl;
use English qw(-no_match_vars);

my $bfn = '../data/AA-backup-xml';
open my $bfh, '<', $bfn or die "Can't read open '$bfn': $OS_ERROR";
my $lfn = '../data/AA-list.txt';
open my $lfh, '<', $lfn or die "Can't read open '$lfn': $OS_ERROR";
my $rfn = '../data/AA-result';
open my $rfh, '>', $rfn or die "Can't write open 'rlfn': $OS_ERROR";
while (my $line = <$bfh>) {
    if ($line =~ /\*{3}/) {
        my $rpl = <$lfh>;
        $rpl = substr($rpl, 0, 3);
        $line =~ s/\*{3}/$rpl/;
    }
    print $rfh $line;
}
close $rfh or die "Can't write close '$rfn': $OS_ERROR";
close $lfh or die "Can't read close '$lfn': $OS_ERROR";
close $bfh or die "Can't read close '$bfn': $OS_ERROR";

输出:

type ..\data\AA-result
whatever
whatever
001 Hosting Services
whatever
whatever
whatever
002 Hosting Services
whatever
whatever
003 Hosting Services
whatever
whatever
whatever
004 Hosting Services

如果这对你不起作用(也许我错误地猜测B的结构或F策略太天真),那么就发布一个代表性的B,L和R样本。

答案 1 :(得分:0)

您可以使用Tie::File通过将文件表示为数组来查看/修改文件,即:

use strict; 
use warnings;
use Tie::File;

tie my @ra1, 'Tie::File', "test.txt" or die; #*** Hosting Services
tie my @ra2, 'Tie::File', "test1.txt" or die; #stuff you want to replace *** with

#assumes equal length
for (my $i=0; $i <= $#ra1; $i++)
{
    my $temp=$ra2[$i];
    $ra1[$i]=~s/(\*{3})/$temp/; 
}

untie @ra1;
untie @ra2;

上面的代码将***替换为列表文件的相应行。通过编写$ra1[$i]=~s/(\*{3})/$temp/,我们将直接更改@ ra1绑定的文件。

答案 2 :(得分:0)

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a linenum=0
(
FOR /f "delims=" %%i IN ('findstr /n "$" ^<backup.xml') DO (
 SET "line=%%i"
 SET "line=!line:*:=!"
 IF DEFINED line (
  IF "!line!"=="*** Hosting Services" (
   SET /a linenum+=1
   FOR /f "tokens=1*delims=:" %%r IN ('findstr /n "$" ^<list.txt') DO (
    IF !linenum!==%%r (ECHO(%%s Hosting Services) 
   )
  ) ELSE (ECHO(!line!)
 ) ELSE (ECHO()
)
)>new.xml

GOTO :eof

IIUC,这应该用"*** Hosting Services"替换backup.xml中的每个line corresponding from list.txt *** Hosting Services行,并创建一个新文件new.xml

答案 3 :(得分:0)

它在awk中非常简短和甜蜜:

awk '
    NR == FNR {list[FNR]=$0; next}
    /\*\*\* Hosting Services/ {sub(/\*\*\*/, list[++count])}
    {print}
' list.txt backup.xml > new_backup.xml

a2p将其转变为

#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if $running_under_some_shell;
            # this emulates #! processing on NIH machines.
            # (remove #! line above if indigestible)

eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
            # process any FOO=bar switches

$, = ' ';       # set output field separator
$\ = "\n";      # set output record separator

line: while (<>) {
    chomp;  # strip record separator
    if ($. == ($.-$FNRbase)) {
        $list{($.-$FNRbase)} = $_;
        next line;
    }
    if (/\*\*\* Hosting Services/) {
        ($s_ = '"'.($list{++$count}).'"') =~ s/&/\$&/g, s/\*\*\*/eval $s_/e;
    }
    print $_;
}
continue {
    $FNRbase = $. if eof;
}