SPUG: itm 60 in effective perl programming
John W. Krahn
krahnj at telus.net
Thu Feb 24 14:09:32 PST 2005
Ben Reser wrote:
> On Thu, Feb 24, 2005 at 02:33:26AM -0800, John W. Krahn wrote:
>
>>>$ echo 'foo' > test
>>>$ echo 'bar' >> test
>>>$ echo 'baz' >> test
>>>$ wc -l test
>>> 3 test
>>>$ perl -pe 's/\n/" " . <>/e' test
>>>foo bar
>>
>>The two lines 'foo' and 'bar' *are* joined together!
>>
>>>baz
>
> Umm but not baz.
>
>
>>>And in fact hangs until you Ctrl+D it if there is an odd number of lines
>>>in the file.
>>
>>It didn't when I tried it and it shouldn't according to the documentation.
>
> It doesn't if you have an even number of lines. An odd number and it
> does.
I feel silly now. I was streaming the the input to the perl program instead
of reading from a file so it worked. To get an odd number of lines from a
file with an even number of lines I was using:
head -n -1 file | perl -pe 's/\n/" " . <>/e'
[big snip]
>>>Perhaps they meant this:
>>>perl -pe 's/\n/ /' file
>>>
>>>tr would probably be moderately better:
>>>perl -pe 'tr/\n/ /'
>>>
>>>But I'd prefer the following:
>>>perl -pe 'chomp; $_ .= " "' file
>>
>>Your examples replace *every* newline with a space which is not what the
>>original does.
>
> Umm yes I realize that. I even explained that. The original doesn't
> join every line. Which isn't what he said it did. It joins every other
> line. Which I suppose if that's what you want is fine but that's not
> what he said it did.
>
>>>I can't imagine why anyone would want to use the regex version.
>>
>>Because the substitution operator allows you to _e_valuate the replacement
>>string as a perl expression.
>
> I'm fully aware of what the original is doing. But if it's described as
> joining all the lines in a file it doesn't do that. Just because you
> can use the regex operator to do something doesn't mean it's the most
> efficient. And many times it's not the most readable.
>
> IMHO this script is seriously bugged. It's misusing the <> operator and
> I'm a bit suprised to hear that it was found in a book titled Effective
> Perl.
I guess you don't have the book? From the chapter "Some interesting Perl
one-liners." in "Effective Perl Programming" page 249:
<QUOTE>
perl -pe 's/\n/" " . <>/e' data
Randal posted something like this in response to a request for a program
that would take lines from a file and join them together in pairs. For
example, here's an input file:
Testing
one
two
three
This one-liner turns the input into the following:
Testing one Each line is two of the old lines
two three joined together with a space.
The -pe command line option used above (a combination of -p and -e)
yields a program that acts like the following:
while (<>) {
s/\n/" " . <>/e;
print;
}
I sputtered a bit when I saw this one-liner for the first time because I had
never thought of using <> in a substitution. But it is fairly straightforward
otherwise. Note that you have to substitute for \n. Nothing else--for exam-
ple, the $ anchor--will work.
</QUOTE>
John
--
use Perl;
program
fulfillment
More information about the spug-list
mailing list