using sed from with a perl script

J

Jack Penarth

I use a perl scrip to parse fixed-length field database outputs into
..csv files. I regularly use a back-ticked sed command to do stuff
after perl has finished with the file ('cos I am not that good with
perl yet!). I have a need to remove the last line of these files and I
thought that the following line would work:

`sed '$d' file.csv > file.csvnew`

But it doesn't. Am I missing something obvious here?

TIA

Jack
 
J

Josef Möllers

Jack said:
I use a perl scrip to parse fixed-length field database outputs into
.csv files. I regularly use a back-ticked sed command to do stuff
after perl has finished with the file ('cos I am not that good with
perl yet!). I have a need to remove the last line of these files and I
thought that the following line would work:

`sed '$d' file.csv > file.csvnew`

But it doesn't. Am I missing something obvious here?

You should have enabled warnings:

Name "main::d" used only once: possible typo at ./pp line 2.
Use of uninitialized value in concatenation (.) at ./pp line 2.

Try
`sed '\$d' file.csv > file.csvnew`

Josef
 
M

Michele Dondi

I use a perl scrip to parse fixed-length field database outputs into
.csv files. I regularly use a back-ticked sed command to do stuff
after perl has finished with the file ('cos I am not that good with
perl yet!). I have a need to remove the last line of these files and I
thought that the following line would work:

`sed '$d' file.csv > file.csvnew`

But it doesn't. Am I missing something obvious here?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

(Apart the serious answer you have already received) I'd guess... the
whole point about using Perl...

As for how to print everything but the last line, there are as usual
tons of WTDI, here's just a try/example:


#!/usr/bin/perl -ni

use strict;
use warnings;

close ARGV if eof;
print our $l unless $.==1;
$l=$_;

__END__


For once this (is simple enough that it) may well have been *not*
strict- and warnings-enabled, but I guess your actual script is
considerably more complex...


Michele
 
F

fifo

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

(Apart the serious answer you have already received) I'd guess... the
whole point about using Perl...

As for how to print everything but the last line, there are as usual
tons of WTDI, here's just a try/example:


#!/usr/bin/perl -ni

use strict;
use warnings;

close ARGV if eof;
print our $l unless $.==1;
$l=$_;

__END__

I think this would be a bit easier:

#!/usr/bin/perl -pi
last if eof
__END__
 
M

Michele Dondi

I think this would be a bit easier:

#!/usr/bin/perl -pi
last if eof
__END__

But since we're not in a Perl golf competition, I would tend to count
this solution as not reliable since, as you surely know, it works for
one file only:

# more test*
::::::::::::::
test1
::::::::::::::
aaaa
bbbb
cccc
dddd
::::::::::::::
test2
::::::::::::::
aaaa
bbbb
cccc
dddd
# ./foo.pl test*
# more test*
::::::::::::::
test1
::::::::::::::
aaaa
bbbb
cccc
::::::::::::::
test2
::::::::::::::
aaaa
bbbb
cccc
dddd

(where of course I called your script foo.pl)

And OTOH next won't work either, since print()ing takes place in a
continue block.

Of course you got the point about "my" solution/example being overly
complex:

#!/usr/bin/perl -ni

next if eof;
print;

__END__

works perfectly though.

As a side note, again since we're not doing a Perl golf competition, I
think it is stylistically recommended to put a semicolon after the
(only) statement in your script in any case...

Well, "my" solution's only advantage is that it can be adapted to the
more general situation in which #n lines are to be discarded:

#!/usr/bin/perl -ni

use strict;
use warnings;

close ARGV if eof;
undef our @l if $. == 1;
print shift @l unless $. < 5;
push @l, $_;

__END__

For some reason I was thinking of something like this when I wrote the
snippet of code in my other posts, but of course I won't ask you to
count this as an excuse...


Michele
 
F

fifo

But since we're not in a Perl golf competition, I would tend to count
this solution as not reliable since, as you surely know, it works for
one file only:

Argh, never even considered calling it with more than one file. In my
defence, I was thinking in terms of replacing the OP's sed call,

`sed '\$d' file.csv > file.csvnew`

with something like

{
open my $in, '<', 'file.csv' or die $!;
open my $out, '>', 'file.csvnew' or die $!;
while (<$in>) {
last if eof;
print;
}
}
As a side note, again since we're not doing a Perl golf competition, I
think it is stylistically recommended to put a semicolon after the
(only) statement in your script in any case...

My personal preference is to omit the semicolon at the end of a
statement that's on its own in a block, but to put semicolons at the end
of all statements if there are more than one. I was just applying this
rule to the admittedly unusual case of a script consisting of one
statement!
 
F

fifo

{
open my $in, '<', 'file.csv' or die $!;
open my $out, '>', 'file.csvnew' or die $!;
while (<$in>) {
last if eof;
print;

Of course that should have been

print $out $_;
 
M

Michele Dondi

Argh, never even considered calling it with more than one file. In my
defence, I was thinking in terms of replacing the OP's sed call,

`sed '\$d' file.csv > file.csvnew`

with something like
[code snipped]

Which is perfectly fine. After all I was not really answering the OP's
question myself.

Just thought it may have been worth to point out that the code now
quoted at the top of this post may be considered risky in the sense
that while working as expected with one file as an argument on the cmd
line, may yield unexpected results if more than one is specified,
which is something not completely unreasonable for "this kind of
scripts", IMHO...
My personal preference is to omit the semicolon at the end of a
statement that's on its own in a block, but to put semicolons at the end
of all statements if there are more than one. I was just applying this
rule to the admittedly unusual case of a script consisting of one
statement!

Well, there's always 'perldoc perlstyle', but as far as I'm concerned
I omit the semicolon *only* if the entire block is on one line, like
thus:

BEGIN { @ARGV=map glob($_), @ARGV }


Michele
 
M

Michele Dondi

Of course that should have been

print $out $_;

Probably you already know, but in case you don't, maybe select() could
be of some interest to you...


Michele
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top