I have one file where the contents looks like:
pch
rch
channel
cap
nch
kappa
.
.
.
kary
ban
....
Now I want to read my file from nch to kary and copying those lines only in some other file. How can I do this in Perl?
I have one file where the contents looks like:
pch
rch
channel
cap
nch
kappa
.
.
.
kary
ban
....
Now I want to read my file from nch to kary and copying those lines only in some other file. How can I do this in Perl?
You could use this in 'sed':
sed -n /nch/,/kary/p $file
You could use 's2p' to convert this to Perl.
You could also write pure Perl:
while (<>)
{
next unless /nch/;
print;
while (<>)
{
print;
last if /kary/;
}
}
Strictly, both these solutions will print each set of lines from 'nch' to 'kary'; if 'nch' appears more than once, it will print more than one chunk of code. It is easy to fix that, especially in the pure Perl ('sed' solution left as an exercise for the reader).
OUTER:
while (<>)
{
next unless /nch/;
print;
while (<>)
{
print;
last OUTER if /kary/;
}
}
Also, the solutions look for 'nch' and 'kary' as part of the line - not for the whole line. If you need them to match the whole line, use '/^nch$/
' etc as the regex.
Something like:
$filter = 0;
while (<>) {
chomp;
$filter = 1 if (! $filter && /^nch$/);
$filter = 0 if ($filter && /^ban$/);
print($_, "\n") if ($filter);
}
should work.
if you only want to read one block, in gawk
gawk '/kary/&&f{print;exit}/nch/{f=1}f' file
in Perl
perl -lne '$f && /kary/ && print && exit;$f=1 if/nch/; $f && print' file
or
while (<>) {
chomp;
if ($f && /kary/) {
print $_."\n";
last;
}
if (/nch/) { $f = 1; }
print $_ ."\n" if $f;
}
If I understand your question correctly, this is pretty simple.
#!perl -w
use strict;
use autodie;
open my $in,'<',"File1.txt";
open my $out,'>',"File2.txt";
while(<$in>){
print $out $_ if /^nch/ .. /^kary/;
}
From perlfaq6's answer to How can I pull out lines between two patterns that are themselves on different lines?
You can use Perl's somewhat exotic .. operator (documented in perlop):
perl -ne 'print if /START/ .. /END/' file1 file2 ...
If you wanted text and not lines, you would use
perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...
But if you want nested occurrences of START through END, you'll run up against the problem described in the question in this section on matching balanced text.
Here's another example of using ..:
while (<>) {
$in_header = 1 .. /^$/;
$in_body = /^$/ .. eof;
# now choose between them
} continue {
$. = 0 if eof; # fix $.
}