问题
I'm not even sure if this is possible, but sure am hoping that it is.
I have this line 766 times in the file backup.xml:
*** Hosting Services
I then have the file list.txt which contains 766 lines in it. I need to replace *** with the contents of each of the 766 lines in list.txt - and it needs to be in the same order if at all possible.
Thanks in advance for any help!
回答1:
Idea:
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)
Plan:
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
Implementation I (read_open, loop, look at 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";
output:
perl 01.pl
whatever
whatever
*** Hosting Services
whatever
whatever
whatever
*** Hosting Services
whatever
whatever
*** Hosting Services
whatever
whatever
whatever
*** Hosting Services
Implementation II (read/write, F, replace, first result):
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";
output:
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
If this does not 'work' for you (perhaps I mis-guessed the structur of B or the F strategy is too naive), then publish a representative sample of B, L, and R.
回答2:
You can use Tie::File to look at/modify files through representing them as arrays, ie:
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;
The above code replaces *** with the corresponding line of your list file. By writing $ra1[$i]=~s/(\*{3})/$temp/ we are directly changing the file that @ra1 is tied to.
回答3:
@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, this should replace each "*** Hosting Services" line from backup.xml with line corresponding from list.txt *** Hosting Services, creating a new file new.xml
回答4:
It's pretty short and sweet in awk:
awk '
NR == FNR {list[FNR]=$0; next}
/\*\*\* Hosting Services/ {sub(/\*\*\*/, list[++count])}
{print}
' list.txt backup.xml > new_backup.xml
a2p turns that into
#!/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;
}
来源:https://stackoverflow.com/questions/16727955/find-and-replace-using-a-list-in-text-file