help with one liners

  • Thread starter Michael Kelly - PCD ~
  • Start date
M

Michael Kelly - PCD ~

Is there a good doc or tutorial source on the web for PERL oneliners?
especially oneliners inside vim?
I especially want to split on commas, and swap $_[55] = $_[61]
as using @F=split(",") ; s/$F[55]/$F[61]/
does not work if $F[1] matches $F[55].
 
P

Paul Lalli

Michael said:
Is there a good doc or tutorial source on the web for PERL oneliners?

perldoc perlrun
I especially want to split on commas, and swap $_[55] = $_[61]

Do you want to *swap* them, or do you want to set the one to the other?
In either case, once that is done, what are you looking to do? Print
out all of the fields to STDOUT? Use @F to recreate the original lines
and print them back to the original file? You need to better define
your goal.
as using @F=split(",") ; s/$F[55]/$F[61]/
does not work if $F[1] matches $F[55].

You need to better define "does not work". Why does it matter if the
2nd element of @F is the same as the 56th element? What does that have
to do with your stated problem goal?

A few clues, since that's the best I can give without knowing more
about your stated problem:

To assign one element of the array @F to another:
$F[55] = $F[61]
To swap the two array positions:
@F[55,61] = @F[61,55];
To turn on auto-splitting:
-a
To specify a comma for the split instead of a space:
-F,
to print the array, separated by commas:
print join(',', @F)

Hope this helps,
Paul Lalli
 
U

usenet

Michael said:
as using @F=split(",") ; s/$F[55]/$F[61]/
does not work if $F[1] matches $F[55].

It does not work no matter what. Because your substitution operation is
bound to the default scalar value $_, not the array @F.

#!/usr/bin/perl
use warnings; use strict;
use Data::Dumper;

my $stuff = join ",", (0..100);

my @F=split(",", $stuff);
@F[61,55] = @F[55,61]; #swap these values
print Dumper \@F; #hey - it works!

__END__
 
G

Glenn Jackman

At 2006-03-15 04:19PM said:
Is there a good doc or tutorial source on the web for PERL oneliners?
especially oneliners inside vim?
I especially want to split on commas, and swap $_[55] = $_[61]
as using @F=split(",") ; s/$F[55]/$F[61]/
does not work if $F[1] matches $F[55].

Perl is not confined to regular expressions alone:

@a = (1,2,3,4,5);
@a[0,-1] = @a[-1,0]; # swap first and last fields
print join(',', @a); # ==> 5,2,3,4,1

As a oneliner, I'd write:

perl -F, -ane '@F[55,61]=@F[61,55]; print join(',',@F),"\n"'

not sure if the trailing newline is required.
 
M

Michael Kelly - PCD ~

Thanks Paul

What I really have a problem with is this works:

perl -pi -e '@_=split; s/$_[2]/85/ ' file

While this does not work:

perl -pi -e '@_=split; $_[2] = 85 ' file

What I really want to do, is this:

perl -pi -e '@_=split; $_[2] = "85" ' file

In some instances, I want to put $_[-1] onto $_[2], and erase $_[-1].
But that's not working either.
 
G

Glenn Jackman

At 2006-03-20 04:07PM said:
What I really have a problem with is this works:

perl -pi -e '@_=split; s/$_[2]/85/ ' file

While this does not work:

perl -pi -e '@_=split; $_[2] = 85 ' file

In the "doesn't work" example, you don't modify $_ so your file will be
unchanged.

Try: perl -i~ -pe 'chomp; @F=split; $F[2]=pop @F; $_=join(" ",@F)."\n"' file
 
G

Glenn Jackman

At 2006-03-20 04:07PM said:
What I really have a problem with is this works:

perl -pi -e '@_=split; s/$_[2]/85/ ' file

While this does not work:

perl -pi -e '@_=split; $_[2] = 85 ' file

In the "doesn't work" example, you don't modify $_ so your file will be
unchanged.

Try: perl -i~ -lape '$F[2]=pop @F; $_=join(" ",@F)' file
 
G

Glenn Jackman

At 2006-03-20 04:07PM said:
What I really have a problem with is this works:

perl -pi -e '@_=split; s/$_[2]/85/ ' file

While this does not work:

perl -pi -e '@_=split; $_[2] = 85 ' file

In some instances, I want to put $_[-1] onto $_[2], and erase $_[-1].
But that's not working either.


In the "doesn't work" example, you don't modify $_ so your file will be
unchanged.

Try: perl -i~ -lape '$F[2]=pop @F; $_=join(" ",@F)' file
 
J

jl_post

Michael said:
What I really have a problem with is this works:

perl -pi -e '@_=split; s/$_[2]/85/ ' file

In order to make it clearer as to what is going on, let's re-write
the code to the following equivalent code:

@fields = split(' ', $_);
$_ =~ s/$fields[2]/85/;

What this code is doing is splitting up the line into the @fields
array, and then searching for the $fields[2] string in $_ (the current
line) and replacing it, if found, with 85.

Notice that, if $fields[2] is a substring that happens to be found
inside one of the current line's previous elements, then that previous
element will be modified instead. For example, if you run that code on
the input:

high low hi hello

you will get the following line of output:

85gh low hi hello

That's because the first instance of "hi" (the third element) is
actually found as a substring of the first element.

If you want to make sure to change ONLY the third element, you might
want to try this line:

perl -wpi -e 's/^(\s*(\S+\s+){2})\S+/${1}85/' file

This specifically looks for two instances of non-whitespace followed by
whitespace (which is then followed by whitespace), and then substitues
what it finds with the first part of the line with your new value.

While this does not work:

perl -pi -e '@_=split; $_[2] = 85 ' file

Here's equivalent code:

@fields = split;
$fields[2] = 85;

Notice that, in this case, nothing is modifying the $_ variable. It's
being used to derive the @fields array (which then gets its third
element set to 85), but nothing actually modifies $_.

What I really want to do, is this:

perl -pi -e '@_=split; $_[2] = "85" ' file

That'll do pretty much the same thing as the previous piece of code
(for the same reasons).
In some instances, I want to put $_[-1] onto $_[2], and erase $_[-1].
But that's not working either.

Well, you can either split apart the fields into an array, modify
the array, and then re-join the array's fields into $_, like this:

perl -lpi -e '@F=split; $F[2]=$F[-1]; pop(@F); $_=join(" ",@F)' file

(The "-l" switch is used so that you don't have to explicitly print out
a newline.)

Incidentally, this code can be easily re-written to use perl's '-a'
switch, with autosplits the current line into the @F array:

perl -lapi -e '$F[2]=$F[-1]; pop(@F); $_=join(" ",@F)' file

Note, however, that this code will separate your fields out with a
single space no matter what whitespace they were separated with before.
If you want to keep the spacing as before, you might want to try
capturing & removing the last element, then substituting the third
element with what you captured:

perl -lpe 's/(\S+)\s*$// and $field=$1,
s/((\S+\s+){2})\S+/$1$field/'

It's not pretty, but it works.

I hope this helps, Michael.

-- Jean-Luc Romano
 

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