From: Rakesh Sharma on
On Nov 24, 2:34 pm, Hongyi Zhao <hongyi.z...(a)gmail.com> wrote:
> Hi all,
>
> I want to swap the appearance order of two lines in a file if needed.
> For detail, please see the following minimal example:
>
> ...
> here_comes_line_b
> ...
> here_comes_line_a
> ...
>
> Suppose the following should be the final result I want:
>
> ...
> here_comes_line_a
> ...
> here_comes_line_b
> ...
>
> Furthermore, in my file, line_a and line_b only occur once.
>
> What code should I use?
> --
> .: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.


perl -F'\n' -00pale '
() = map { /line_[ab]/ && do{$h{$&}=[$i,$_];};++$i; } @F;
$f = ($h{line_a}->[0] > $h{line_b}->[0]) ? -1 : 0;
splice(@F, $f+$h{line_a}->[0], 1, $h{line_a}->[1], splice(@F, $h
{line_b}->[0], 1));
$_ = join "\n", @F;
' yourfile

Note: empty lines will be discarded. This may or may not be what you
want.
From: John W. Krahn on
Rakesh Sharma wrote:
> On Nov 24, 2:34 pm, Hongyi Zhao <hongyi.z...(a)gmail.com> wrote:
>>
>> I want to swap the appearance order of two lines in a file if needed.
>> For detail, please see the following minimal example:
>>
>> ...
>> here_comes_line_b
>> ...
>> here_comes_line_a
>> ...
>>
>> Suppose the following should be the final result I want:
>>
>> ...
>> here_comes_line_a
>> ...
>> here_comes_line_b
>> ...
>>
>> Furthermore, in my file, line_a and line_b only occur once.
>>
>> What code should I use?
>> --
>> .: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.
>
>
> perl -F'\n' -00pale '
> () = map { /line_[ab]/ && do{$h{$&}=[$i,$_];};++$i; } @F;
> $f = ($h{line_a}->[0] > $h{line_b}->[0]) ? -1 : 0;
> splice(@F, $f+$h{line_a}->[0], 1, $h{line_a}->[1], splice(@F, $h
> {line_b}->[0], 1));
> $_ = join "\n", @F;
> ' yourfile
>
> Note: empty lines will be discarded. This may or may not be what you
> want.

That doesn't appear to work correctly:

$ echo "one
two
line_b
four
five
six
line_a
eight
nine" | perl -F'\n' -00pale'
() = map { /line_[ab]/ && do{$h{$&}=[$i,$_];};++$i; } @F;
$f = ($h{line_a}->[0] > $h{line_b}->[0]) ? -1 : 0;
splice(@F, $f + $h{line_a}[0], 1, $h{line_a}->[1], splice(@F,
$h{line_b}->[0], 1));
$_ = join "\n", @F;
'
one
two
four
five
six
line_a
line_b
eight
nine


That doesn't properly exchange 'line_a' and 'line_b'. This appears to
work better:

$ echo "one
two
line_b
four
five
six
line_a
eight
nine" | perl -F'\n' -0777pae'
$F[ $_ ] =~ /line_([ab])/ and $h{ $1 } = $_ for 0 .. $#F;
@F[ @h{ qw/a b/ } ] = @F[ @h{ qw/b a/ } ];
$_ = join "\n", @F;
'
one
two
line_a
four
five
six
line_b
eight
nine




John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity. -- Damian Conway
From: Rakesh Sharma on
On Nov 30, 6:01 pm, "John W. Krahn" <some...(a)example.com> wrote:
> Rakesh Sharma wrote:
> > On Nov 24, 2:34 pm, Hongyi Zhao <hongyi.z...(a)gmail.com> wrote:
>
> >> I want to swap the appearance order of two lines in a file if needed.
> >> For detail, please see the following minimal example:
>
> >> ...
> >> here_comes_line_b
> >> ...
> >> here_comes_line_a
> >> ...
>
> >> Suppose the following should be the final result I want:
>
> >> ...
> >> here_comes_line_a
> >> ...
> >> here_comes_line_b
> >> ...
>
> >> Furthermore, in my file, line_a and line_b only occur once.
>
> >> What code should I use?
> >> --
> >> .: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.
>
> > perl -F'\n' -00pale '
> >    () = map { /line_[ab]/ && do{$h{$&}=[$i,$_];};++$i; } @F;
> >    $f = ($h{line_a}->[0] > $h{line_b}->[0]) ? -1 : 0;
> >    splice(@F, $f+$h{line_a}->[0], 1, $h{line_a}->[1], splice(@F, $h
> > {line_b}->[0], 1));
> >    $_ = join "\n", @F;
> > '  yourfile
>
> > Note: empty lines will be discarded. This may or may not be what you
> > want.
>
> That doesn't appear to work correctly:
>
> $ echo "one
> two
> line_b
> four
> five
> six
> line_a
> eight
> nine" | perl -F'\n' -00pale'
>      () = map { /line_[ab]/ && do{$h{$&}=[$i,$_];};++$i; } @F;
>      $f = ($h{line_a}->[0] > $h{line_b}->[0]) ? -1 : 0;
>      splice(@F, $f + $h{line_a}[0], 1, $h{line_a}->[1], splice(@F,
> $h{line_b}->[0], 1));
>      $_ = join "\n", @F;
> '
> one
> two
> four
> five
> six
> line_a
> line_b
> eight
> nine
>
> That doesn't properly exchange 'line_a' and 'line_b'.  This appears to
> work better:
>
> $ echo "one
> two
> line_b
> four
> five
> six
> line_a
> eight
> nine" | perl -F'\n' -0777pae'
>      $F[ $_ ] =~ /line_([ab])/ and $h{ $1 } = $_ for 0 .. $#F;
>      @F[ @h{ qw/a b/ } ] = @F[ @h{ qw/b a/ } ];
>      $_ = join "\n", @F;
> '
> one
> two
> line_a
> four
> five
> six
> line_b
> eight
> nine
>
> John
> --
> The programmer is fighting against the two most
> destructive forces in the universe: entropy and
> human stupidity.               -- Damian Conway


Thanks for pointing it out!

I was working under the assumption given by the OT as:

>>> 1- If line_b appears just immediately after line_a, then do nothing.

>>> 2- In other cases, move line_b to make sure it just immediately after line_a.

He doesn't want to swap the positions of line_a <=> line_b, rather he
just wants to place line_b under line_a.
So that's the basic premise I used to write it.

But I had a few questions of my own.

1) What's the difference between perl -00pae & perl -0777pae?
I used perl -00 to intend "slurping". The perl manual lists that
we use -0777 as you have used also.

2) In the line that I wrote: () = map { /line_[ab]/ && do{$h{$&}=[$i,
$_];};++$i; } @F;
I remember being forced to put that do{} construct in otherwise
it gave an error. Whereas, if I take a look
at what you wrote: $F[ $_ ] =~ /line_([ab])/ and $h{ $1 } = $_
for 0 .. $#F;
Why didn't perl blurt out in this case?

Thanks for your patience,
TIA

--Rakesh
From: John W. Krahn on
Rakesh Sharma wrote:
>
> Thanks for pointing it out!
>
> I was working under the assumption given by the OT as:
>
>>>> 1- If line_b appears just immediately after line_a, then do nothing.
>
>>>> 2- In other cases, move line_b to make sure it just immediately after line_a.
>
> He doesn't want to swap the positions of line_a <=> line_b, rather he
> just wants to place line_b under line_a.
> So that's the basic premise I used to write it.
>
> But I had a few questions of my own.
>
> 1) What's the difference between perl -00pae & perl -0777pae?
> I used perl -00 to intend "slurping". The perl manual lists that
> we use -0777 as you have used also.

The -00 option uses the "\0" (the ASCII NUL) character as the Input
Record Separator which should not appear in a text file, but might, and
-0777 sets the Input Record Separator to an invalid value so it will
always properly slurp the entire file.


> 2) In the line that I wrote: () = map { /line_[ab]/ && do{$h{$&}=[$i,
> $_];};++$i; } @F;
> I remember being forced to put that do{} construct in otherwise
> it gave an error. Whereas, if I take a look
> at what you wrote: $F[ $_ ] =~ /line_([ab])/ and $h{ $1 } = $_
> for 0 .. $#F;
> Why didn't perl blurt out in this case?

The '&&' operator has higher precedence than the '=' operator which will
produce a error message:

$ perl -le' $ARGV[0] && $x = 123 ' 789
Can't modify logical and (&&) in scalar assignment at -e line 1, at EOF
Execution of -e aborted due to compilation errors.

Whereas the 'and' operator has lower precedence than the '=' operator so
it will work properly:

$ perl -le' $ARGV[0] and $x = 123 ' 789

If you want to use the '&&' operator you will have to enclose the
assignment in parentheses:

$ perl -le' $ARGV[0] && ( $x = 123 ) ' 789




John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity. -- Damian Conway
From: John W. Krahn on
Rakesh Sharma wrote:
>
> Thanks for pointing it out!
>
> I was working under the assumption given by the OT as:
>
>>>> 1- If line_b appears just immediately after line_a, then do nothing.
>
>>>> 2- In other cases, move line_b to make sure it just immediately after line_a.
>
> He doesn't want to swap the positions of line_a <=> line_b, rather he
> just wants to place line_b under line_a.
> So that's the basic premise I used to write it.
>
> But I had a few questions of my own.
>
> 1) What's the difference between perl -00pae & perl -0777pae?
> I used perl -00 to intend "slurping". The perl manual lists that
> we use -0777 as you have used also.

The -00 option uses the "\0" (the ASCII NUL) character as the Input
Record Separator which should not appear in a text file, but might, and
-0777 sets the Input Record Separator to an invalid value so it will
always properly slurp the entire file.


> 2) In the line that I wrote: () = map { /line_[ab]/ && do{$h{$&}=[$i,
> $_];};++$i; } @F;
> I remember being forced to put that do{} construct in otherwise
> it gave an error. Whereas, if I take a look
> at what you wrote: $F[ $_ ] =~ /line_([ab])/ and $h{ $1 } = $_
> for 0 .. $#F;
> Why didn't perl blurt out in this case?

The '&&' operator has higher precedence than the '=' operator which will
produce a error message:

$ perl -le' $ARGV[0] && $x = 123 ' 789
Can't modify logical and (&&) in scalar assignment at -e line 1, at EOF
Execution of -e aborted due to compilation errors.

Whereas the 'and' operator has lower precedence than the '=' operator so
it will work properly:

$ perl -le' $ARGV[0] and $x = 123 ' 789

If you want to use the '&&' operator you will have to enclose the
assignment in parentheses:

$ perl -le' $ARGV[0] && ( $x = 123 ) ' 789



John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity. -- Damian Conway