3
\$\begingroup\$

Here is a simple program that I created to print a file by breaking it after a fixed number of columns. I feel it can be optimized but not sure how. Any feedback is great.

#This is a simple program that takes a file and the limits the columns length to
#the number passed in as second argument
if ($#ARGV < 1) {
 printf("Usage: perl %s <name of the input file> <column length>\n", 0ドル);
 exit(-1);
}
$file=$ARGV[0];
open(INFO, $file) or die("Could not open file.");
$LINE_LENGTH = $ARGV[1];
$count = 0;
foreach $line (<INFO>) {
 #print $line;
 if (length($line) <= $LINE_LENGTH) {
 printf("%s\n", $line);
 } else {
 $remaining_chars = length ($line);
 $remaining_line = $line;
 while ($remaining_chars >= $LINE_LENGTH) {
 $cur_str = substr($remaining_line, 0, $LINE_LENGTH - 1 );
 printf("%s\n", $cur_str );
 $remaining_line = substr($remaining_line, $LINE_LENGTH - 1);
 $remaining_chars = $remaining_chars - length($cur_str);
 }
 printf("%s",$remaining_line );
 }
 if ($++counter == 2){
 last;
 }
}
printf("\n");
close(INFO);
rolfl
98.1k17 gold badges219 silver badges419 bronze badges
asked Oct 14, 2015 at 21:51
\$\endgroup\$
1

3 Answers 3

4
\$\begingroup\$

I am not sure it can be optimized in a sense of better performance. It could be streamlined though. The initial test for length($line) <= $LINE_LENGTH is just redundant. Compare:

 while (length ($line) > LINE_LENGTH) {
 $prefix = substr($line, 0, $LINE_LENGTH - 1 );
 $line = substr($line, $LINE_LENGTH - 1);
 printf("%s\n", $prefix);
 }
 printf("%s",$line );

PS: I am not familiar with perl enough. If there is a split at position function, you may use it instead of calling substr twice.

answered Oct 14, 2015 at 22:45
\$\endgroup\$
2
\$\begingroup\$

You can use regular expression instead of substr(),

use strict;
use warnings;
if (@ARGV != 2) {
 die("Usage: perl 0ドル <name of the input file> <column length>\n");
} 
my ($file, $LINE_LENGTH) = @ARGV;
open(my $INFO, "<", $file) or die($!);
my $count = 0;
while (my $line = <$INFO>) {
 print 1,ドル "\n" while $line =~ /( .{1,$LINE_LENGTH} )/xg;
 # ...
 if (++$count == 2) {
 last;
 }
}
print "\n";
close($INFO);
answered Oct 15, 2015 at 3:20
\$\endgroup\$
2
\$\begingroup\$

use strict;

^^^ always.

You will be saved from embarassing things, like this:

if ($++counter == 2){
 last;
}

Seriously, what is that? ;-)

With perl it's often best to put required arguments first, and then use ARGV magic to handle the input files. In other words, put the column width first, and then the input files... The ARGV magic is powerful, it will read all the files given on the commandline, or, read the STDIN if no files are given. By shifting the column width off the @ARGV you can let the magic do its thing.

chomp is another nice trick, it removes any trailing newlines, if any.

The lines can be printed with brute-force substrings in a while loop then.

I would write your code as:

#!/usr/bin/perl
my $cols = shift @ARGV;
# Set a default, if empty
$cols ||= 80;
while (my $line = <>) {
 chomp $line;
 while (length($line) > $cols) {
 print substr($line, 0, $cols) . "\n";
 $line = substr($line, $cols);
 }
 print $line . "\n";
}

Note, assuming this is saved as a file called "narrow", then this can now be called in many ways:

  • narrow 80 *.java
  • curl http://example.com | narrow
  • curl http://example.com | narrow 120
  • etc.
answered Oct 15, 2015 at 3:08
\$\endgroup\$
4
  • \$\begingroup\$ for my $line (<>) => while (my $line = <>) \$\endgroup\$ Commented Oct 15, 2015 at 3:24
  • \$\begingroup\$ @mpapec - hmm.. i should run things before answering.... checking now. \$\endgroup\$ Commented Oct 15, 2015 at 3:26
  • \$\begingroup\$ while doesn't slurp a whole file into memory stackoverflow.com/questions/585341/… \$\endgroup\$ Commented Oct 15, 2015 at 3:27
  • \$\begingroup\$ @mpapec - yeah, and even the for should have been a foreach, I think, without the slurp (actually, not so much a slurp, but a non-scalar context). \$\endgroup\$ Commented Oct 15, 2015 at 3:29

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.