How can I write only certain lines of a file in Perl?

I am looking for a way to read the input file and print only the selection lines to the output file in Perl. The lines that I want to print in the output file begin with xxxx.xxxx.xxxx , where x is an alphanumeric character (periods are periods, not wildcards). Lines do not all have the same end, if that matters. I think something like the following (the condition of the if is all that is really missing, as far as I can tell).

 open(IN, "<$csvfile"); my @LINES = <IN>; close(IN); open(OUT, ">$csvnewfile"); print OUT @LINES if ([line starts with xxxx.xxxx.xxxx]); close(OUT); 

Thanks in advance!

+7
regex grep perl csv
source share
7 answers

Here is the best way to iterate over your lines. This avoids loading your entire input file into memory immediately:

 use strict; use warnings; open my $fhi, '<', $csvfile or die "Can not open file $csvfile: $!"; open my $fho, '>', $csvnewfile or die "Can not open file $csvnewfile: $!"; while (<$fhi>) { print $fho $_ if m/^ \w{4} \. \w{4} \. \w{4} /x; } close $fho; close $fhi; 

Keep in mind that the \w character class also includes underscores. To avoid underlining:

 print $fho $_ if m/^ [az\d]{4} \. [az\d]{4} \. [az\d]{4} /xi; 
+8
source share

Style Tips:

  • use lexical file descriptors
  • check open result
  • it’s also a good idea to check the close result on a write descriptor

See below:

 #! /usr/bin/perl use warnings; use strict; die "Usage: $0 old new\n" unless @ARGV == 2; my($csvfile,$csvnewfile) = @ARGV; open my $in, "<", $csvfile or die "$0: open $csvfile: $!"; open my $out, ">", $csvnewfile or die "$0: open $csvnewfile: $!"; while (<$in>) { print $out $_ if /^\w{4}\.\w{4}\.\w{4}/; } close $out or warn "$0: close $csvnewfile: $!"; 
+3
source share

using grep

  grep "^\w\{4\}\.\w\{4\}\.\w\{4\}\b" file 
+2
source share
 if ($_ =~ m/^\w{4}\.\w{4}\.\w{4}/i) 

I think. My perl is a little rusty.

+1
source share

From perlfaq5 the answer to How do I change, delete or insert a line in a file, or add to the beginning of a file?


The basic idea of ​​inserting, changing, or deleting a line from a text file is to read and print the file to the point where you want to make changes, make changes, then read and print the rest of the file. Perl does not provide random access to strings (all the more so since the entry separator, $ /, has been changed), although modules such as Tie :: File can fake it.

The Perl program for these tasks takes the basic form of opening a file, printing its lines and closing the file:

 open my $in, '<', $file or die "Can't read old file: $!"; open my $out, '>', "$file.new" or die "Can't write new file: $!"; while( <$in> ) { print $out $_; } 

close $ out; In this basic form, add the parts you need to insert, modify, or delete rows.

To add lines to the beginning, print these lines before entering a loop that prints existing lines.

 open my $in, '<', $file or die "Can't read old file: $!"; open my $out, '>', "$file.new" or die "Can't write new file: $!"; print $out "# Add this line to the top\n"; # <--- HERE THE MAGIC while( <$in> ) { print $out $_; } 

close $ out; To modify existing rows, insert code to modify rows within a while loop. In this case, the code finds all lower versions of "perl" and upper case. This happens for every line, so make sure you do this on every line!

 open my $in, '<', $file or die "Can't read old file: $!"; open my $out, '>', "$file.new" or die "Can't write new file: $!"; print $out "# Add this line to the top\n"; while( <$in> ) { s/\b(perl)\b/Perl/g; print $out $_; } 

close $ out; To change only a specific line, it is useful to use the input line number $. First read and print the lines to the ones you want to change. Then read the one line you want to change, change it and print. After that, read the rest of the lines and print them:

 while( <$in> ) # print the lines before the change { print $out $_; last if $. == 4; # line number before change } my $line = <$in>; $line =~ s/\b(perl)\b/Perl/g; print $out $line; while( <$in> ) # print the rest of the lines { print $out $_; } 

To skip lines, use loop controls. The next one in this example skips the comment lines, and the last one stops all processing when it encounters either END or DATA .

 while( <$in> ) { next if /^\s+#/; # skip comment lines last if /^__(END|DATA)__$/; # stop at end of code marker print $out $_; } 

Do the same to delete a specific line using the following command to skip lines that you do not want to display in the output. This example skips every fifth line:

 while( <$in> ) { next unless $. % 5; print $out $_; } 

If for some odd reason you really want to see the entire file at the same time, and not process it in turn, you can split it (for now, you can put all this into memory!):

 open my $in, '<', $file or die "Can't read old file: $!" open my $out, '>', "$file.new" or die "Can't write new file: $!"; my @lines = do { local $/; <$in> }; # slurp! # do your magic here print $out @lines; 

Modules such as File :: Slurp and Tie :: File can also help with this. However, if you cannot read the entire file at once. Perl does not return this memory to the operating system until the process is complete.

You can also use single-line Perl to modify the file in place. The following changes all “Fred” to “Barney” in inFile.txt, overwriting the file with the new contents. Using the -p switch, Perl ends the while loop with the code specified with -e, and -i enables in-place editing. The current line is in $. With -p, Perl automatically prints the $ value at the end of the loop. See Perlrun for more details.

 perl -pi -e 's/Fred/Barney/' inFile.txt 

To backup inFile.txt, give the -i file extension to add:

 perl -pi.bak -e 's/Fred/Barney/' inFile.txt 

To change only the fifth line, you can add the verification check $., The line number of the input, and then only perform the operation when the test passes:

 perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt 

To add lines to a specific line, you can add a line (or lines!) Before Perl prints $ _:

 perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt 

You can even add a line to the beginning of the file, as the current line prints at the end of the loop:

 perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt 

To insert a line after one into the file, use the -n switch. This is exactly the same as -p, except that it does not print $ _ at the end of the loop, so you have to do it yourself. In this case, print $ _ first, then print the line you want to add.

 perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt 

To delete lines, print only the ones you want.

 perl -ni -e 'print unless /d/' inFile.txt ... or ... perl -pi -e 'next unless /d/' inFile.txt 
+1
source share

If you do not mind leaving it on command line 1:

 perl -ne "print if /^.{4}[.].{4}[.].{4}/" csvfile.csv > csvnewfile.csv 
0
source share
 perl -ne 'print if /^\w{4}\.\w{4}\.\w{4}\b/' file > newfile.csv 
0
source share

All Articles