views:

142

answers:

6

I'd like to replace (as an example) the text of lines 5-15 in a file with the text from lines 6-15 from another file. But I'd like to do this over about 2000 files, and would rather not have to do it manually.

I could script something in perl, but I'd like to try to do it with any built-ins possible.

+4  A: 

If you're not going to use Perl, probably the leading other candidate is sed or maybe awk, but all three are pretty similar. I would just go ahead and use Perl. It's designed for this sort of thing.

David Zaslavsky
+2  A: 

Use Perl, or if you don't like Perl, Ruby or Python. You could do this with the shell, but it will be ultimately more complicated than writing a small program to handle the job.

Don Werve
+3  A: 

Sometimes, when all you have is a hammer, your problem really is a loose nail.

Mark Ransom
+1  A: 

I'm hardly an expert on these things, but I would think this could be done with a simple ed script. I do not know how to write such an ed script, however. ed is pretty much guaranteed to be on any *nix system, so I think it meets the same level of availability as "builtins".

rmeador
+4  A: 
for files in PATTERN ; do
  sed -n '1,14p' $files > newfile.$files
  sed -n '6,15p' ANOTHERFILE >> newfile.$files
  sed -n '15,$p' $files >> newfile.$files
done

Note: it's not resource effecient, but I'm writing it on a really powerful server ;-) And there are several other ways to do it.

Zsolt Botykai
Sed is the way to go here! It was designed for this task.
Jordan
Since the files are iterated one after one, I feel it would be clearer and better to write "for file in ..." instead of "for files in ...".
hlovdal
You're right from a grammar point of view. And from subjective point of view: I can name my variables like cVGHJJKAHFDJHSJFO9878932KHJKHJK too. If I can understand it later.
Zsolt Botykai
+2  A: 

I'd probably use sed

for file in bar baz bam; do
    newfile=$(mktemp)
    (sed '5q' $file; sed -n '6,15p' foo; sed '1,15d' $file) > $newfile
    mv -f $newfile $file
done

or Perl

#!/usr/bin/env perl

use v5.6;  # lexical filehandles need Perl >= 5.6

# usage: $0 foo bar baz bam
# replaces lines 4-15 of qw(bar baz bam) with lines 6-15 of foo 

my @ins;

{
    open my $fh, shift;
    while (<$fh>) {
        push @ins, $_ if 6 .. 15;
        last if $. >= 15;
    }
}

$^I = '';

while (<>) {
    print if not 5 .. 15;
    print @ins if $. == 4;
}
continue {
    close ARGV if eof ARGV;
}

but ed works too.

echo '6,15wq foo-part' | ed foo
for i in bar baz bam; do
    echo -e '5,15d\n4r foo-part\nwq' | ed $i
done
rm -f foo-part
ephemient