Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Swap the appearance order of two lines if needed.

5 views
Skip to first unread message

Hongyi Zhao

unread,
Nov 24, 2009, 4:34:47 AM11/24/09
to
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 :.

WANG Cong

unread,
Nov 24, 2009, 8:05:54 AM11/24/09
to
On Tue, 24 Nov 2009 17:34:47 +0800, Hongyi Zhao 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?

perl -e '@_ = <STDIN>; ($_[$ARGV[0]-1], $_[$ARGV[1]-1])=($_[$ARGV[1]-1],
$_[$ARGV[0]-1]); print @_;' `grep -n here_comes_line_b your_file | cut -
d: -f1` `grep -n here_comes_line_a your_file | cut -d: -f1` < your_file


Ed Morton

unread,
Nov 24, 2009, 8:12:18 AM11/24/09
to
Hongyi Zhao 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?

Either use an array to hold the whole file:

awk '{file[NR]=$0} /here_comes_line_a|here_comes_line_b/{swap[++cnt]=NR}
END{ tmp=file[swap[1]]; file[swap[1]]=file[swap[2]]; file[swap[2]]=tmp
for (i=1;i<=NR;i++) print file[i] }' file

or do two passes of the file:

awk 'NR==FNR{ if (/here_comes_line_a/) a[NR]=$0
else if (/here_comes_line_b/) b[NR]=$0
next
}
NR in a { $0 = b[NR] }
NR in b { $0 = a[NR] }
1' file file

Both untested.

Regards,

Ed.

Glenn Jackman

unread,
Nov 24, 2009, 10:12:28 AM11/24/09
to

Or, in one pass, store just line_b and the intermediate lines:

awk '
BEGIN { lineb = ""; counter = 0 }
/here_comes_line_b/ { lineb = $0; next }
/here_comes_line_a/ {
print
for (i = 1; i <= counter; i++) {print store[i]}
print lineb
lineb = ""
next
}
lineb != "" { store[++counter] = $0; next }
1 {print}
' file


--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous

Kaz Kylheku

unread,
Nov 24, 2009, 12:05:48 PM11/24/09
to
On 2009-11-24, Hongyi Zhao <hongy...@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?

www.nongnu.org/txr

$ txr -c \
'@(collect)
@ prolog
@ (until)
here_comes_line_b
@(end)
@ line_b
@(collect)
@ middle
@ (until)
here_comes_line_a
@(end)
@line_a
@(collect)
@ epilog
@(end)
@(output)
@ (repeat)
@ prolog
@ (end)
@ line_a
@ (repeat)
@ middle
@ (end)
@ line_b
@ (repeat)
@ epilog
@ (end)
@(end)' file

Simple logic: ``Collect the prologue material until the pattern for line
B is seen. Then collect that line. Collect the middle material unil
line A is seen. Collect that line. Then collect the trailing material.
Produce the material in the right order.''

I.e. we express the whole task as a pattern match for the entire file,
with embedded variable bindings, and regurgitate in a different order.

This txr query will nicely return a failed termination status and not produce
any output if the file does not match the pattern.

This could be done differently. Once line A is processed, the prologue,
line A, middle part and line B could be output immediately. Then,
an arbitrarily amount of epilogue could be copied using a constant
amount of memory. This would be useful if the two lines to be swapped
occur near the beginning of a huge file.

$ txr -c \
'@(collect)
@ prolog
@ (until)
here_comes_line_b
@(end)
@line_b
@(collect)
@ middle
@ (until)
here_comes_line_a
@(end)
@line_a
@(output)
@ (repeat)
@ prolog
@ (end)
@ line_a
@ (repeat)
@ middle
@ (end)
@ line_b
@(end)
@(collect)
@ epilog
@ (output)
@ epilog
@ (end)
@ (forget epilog)
@(end)' yourfile

Rakesh Sharma

unread,
Nov 24, 2009, 3:22:17 PM11/24/09
to


Provided there's atleast one line between line_a & line_b we can do
this:

sed -e '
/\n/b
/re1/,/re2/!b
/re2/!H;/re1/h;/re2/!d
p;g;s/\n.*//;H;g;D
' yourfile

Hongyi Zhao

unread,
Nov 25, 2009, 9:33:14 PM11/25/09
to
On Tue, 24 Nov 2009 12:22:17 -0800 (PST), Rakesh Sharma
<shar...@hotmail.com> wrote:

>Provided there's atleast one line between line_a & line_b we can do
>this:

In my case, the line_b sometimes just immediately appear before
line_a, i.e.,

line_b
line_a

How should your code be changed in order to deal with both cases?

>
>sed -e '
> /\n/b
> /re1/,/re2/!b
> /re2/!H;/re1/h;/re2/!d
> p;g;s/\n.*//;H;g;D
>' yourfile

So complicated for me to understand, any hints on your code?

Best regards.

Hongyi Zhao

unread,
Nov 25, 2009, 9:43:44 PM11/25/09
to
On Tue, 24 Nov 2009 17:34:47 +0800, Hongyi Zhao
<hongy...@gmail.com> wrote:

>Suppose the following should be the final result I want:
>
>...
>here_comes_line_a
>...
>here_comes_line_b
>...

Oops, in fact, I want to obtain the following final result:

...
...
here_comes_line_a
here_comes_line_b
...

I.e., line_a should appear just immediately before line_b. Thanks
again.

Ed Morton

unread,
Nov 25, 2009, 10:02:04 PM11/25/09
to
Hongyi Zhao wrote:
> On Tue, 24 Nov 2009 17:34:47 +0800, Hongyi Zhao
> <hongy...@gmail.com> wrote:
>
>> Suppose the following should be the final result I want:
>>
>> ...
>> here_comes_line_a
>> ...
>> here_comes_line_b
>> ...
>
> Oops, in fact, I want to obtain the following final result:
>
> ...
> ...
> here_comes_line_a
> here_comes_line_b
> ...
>
> I.e., line_a should appear just immediately before line_b. Thanks
> again.

So, is there actually any swapping involved or do you just want to save line_a
and print it before line_b?

Ed.

Hongyi Zhao

unread,
Nov 25, 2009, 10:51:05 PM11/25/09
to
On Wed, 25 Nov 2009 21:02:04 -0600, Ed Morton <morto...@gmail.com>
wrote:

>So, is there actually any swapping involved or do you just want to save line_a
>and print it before line_b?

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

Best regards.

Ed Morton

unread,
Nov 25, 2009, 11:41:04 PM11/25/09
to
Hongyi Zhao wrote:
> On Wed, 25 Nov 2009 21:02:04 -0600, Ed Morton <morto...@gmail.com>
> wrote:
>
>> So, is there actually any swapping involved or do you just want to save line_a
>> and print it before line_b?
>
> 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
>
> Best regards.

OK, so you don't actually want to swap anything, you want to find "line_b" and
move it to earlier in the file, specifically right after "line_a", right? try this:

tac file | awk '/line_b/{b=$0 RS; next} /line_a/{printf "%s",b} 1' | tac

Ed.

Hongyi Zhao

unread,
Nov 26, 2009, 12:46:00 AM11/26/09
to
On Wed, 25 Nov 2009 22:41:04 -0600, Ed Morton <morto...@gmail.com>
wrote:

>OK, so you don't actually want to swap anything, you want to find "line_b" and

>move it to earlier in the file, specifically right after "line_a", right? try this:
>
>tac file | awk '/line_b/{b=$0 RS; next} /line_a/{printf "%s",b} 1' | tac

Let me give a minimal example:

$ cat test_swap2lines.txt
some_others1
line_b
some_others2
line_a
some_others3

I want to obtain the following result:

some_others1
some_others2
line_a
line_b
some_others3

But, your above code will give something like this:

$ tac test_swap2lines.txt | awk '/line_b/{b=$0 RS; next}


/line_a/{printf "%s",b
} 1' | tac

some_others1
some_others2
line_a
some_others3

In the result given by your code, the line_b is removed from the
result, which is not the result I want.

w_a_x_man

unread,
Nov 26, 2009, 4:47:17 AM11/26/09
to
On Nov 25, 11:46 pm, Hongyi Zhao <hongyi.z...@gmail.com> wrote:
> On Wed, 25 Nov 2009 22:41:04 -0600, Ed Morton <mortons...@gmail.com>

Using Ruby:

# Read the file.
gets(nil)
# Remove Line B.
sub!( /.*line_b.*\n/, "" )
# Remember Line B.
b = $&
# Insert Line B after Line A.
puts sub( /line_a.*\n/, '\&' + b )

Hongyi Zhao

unread,
Nov 26, 2009, 7:25:35 AM11/26/09
to
On Thu, 26 Nov 2009 01:47:17 -0800 (PST), w_a_x_man
<w_a_...@yahoo.com> wrote:

>Using Ruby:
>
># Read the file.
>gets(nil)
># Remove Line B.
>sub!( /.*line_b.*\n/, "" )
># Remember Line B.
>b = $&
># Insert Line B after Line A.
>puts sub( /line_a.*\n/, '\&' + b )

Very good, thanks a lot, you let me know a succinct and powerful tool.

Hongyi Zhao

unread,
Nov 26, 2009, 7:37:27 AM11/26/09
to
On Thu, 26 Nov 2009 01:47:17 -0800 (PST), w_a_x_man
<w_a_...@yahoo.com> wrote:

>Using Ruby:
>
># Read the file.
>gets(nil)
># Remove Line B.
>sub!( /.*line_b.*\n/, "" )
># Remember Line B.
>b = $&
># Insert Line B after Line A.
>puts sub( /line_a.*\n/, '\&' + b )

Is it possible to edit the input file in place by uisng ruby, i.e.,
just like the -i OPTION for sed?

w_a_x_man

unread,
Nov 26, 2009, 4:37:15 PM11/26/09
to
On Nov 26, 6:37 am, Hongyi Zhao <hongyi.z...@gmail.com> wrote:
> On Thu, 26 Nov 2009 01:47:17 -0800 (PST), w_a_x_man
>
> <w_a_x_...@yahoo.com> wrote:
> >Using Ruby:
>
> ># Read the file.
> >gets(nil)
> ># Remove Line B.
> >sub!( /.*line_b.*\n/, "" )
> ># Remember Line B.
> >b = $&
> ># Insert Line B after Line A.
> >puts sub( /line_a.*\n/, '\&' + b )
>
> Is it possible to edit the input file in place by uisng ruby, i.e.,
> just like the -i OPTION for sed?

Yes.
ruby -i.bak -pe'gsub( "c", "x" )' data

This makes a backup file named "data.bak" and replaces
each "c" with "x".

Hongyi Zhao

unread,
Nov 26, 2009, 9:16:37 PM11/26/09
to
On Thu, 26 Nov 2009 13:37:15 -0800 (PST), w_a_x_man
<w_a_...@yahoo.com> wrote:

>Yes.
>ruby -i.bak -pe'gsub( "c", "x" )' data
>
>This makes a backup file named "data.bak" and replaces
>each "c" with "x".

Good, thanks again. I want to do the inplace edit without backup file
generated. What option should I use?

Rakesh Sharma

unread,
Nov 27, 2009, 4:52:58 AM11/27/09
to
On Nov 26, 7:33 am, Hongyi Zhao <hongyi.z...@gmail.com> wrote:
> On Tue, 24 Nov 2009 12:22:17 -0800 (PST), Rakesh Sharma
>
> <sharma...@hotmail.com> wrote:
> >Provided there's atleast one line between line_a & line_b we can do
> >this:
>
> In my case, the line_b sometimes just immediately appear before
> line_a, i.e.,
>
> line_b
> line_a
>
> How should your code be changed in order to deal with both cases?
>
>
>
> >sed -e '
> >   /\n/b
> >   /re1/,/re2/!b
> >   /re2/!H;/re1/h;/re2/!d
> >   p;g;s/\n.*//;H;g;D
> >' yourfile
>
> So complicated for me to understand, any hints on your code?
>
> Best regards.
> --
> .: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.


As you have stated that you want to align line_a then line_b no matter
where they come in the file.
& they occur just once in the file.

sed -ne '
/line_a/ba
/line_b/bb
p;d

:a
p;n;/line_b/bspin
:notb
/line_b/!{
H;n
bnotb
}
p;g;s/.//;bspin

:b
h;n
:nota
/line_a/!{
p;n
bnota
}
G;bspin

:spin
p;$d;n
bspin
' yourfile

-- Rakesh

WANG Cong

unread,
Nov 27, 2009, 10:41:18 AM11/27/09
to
On 11/26/09 11:51, Hongyi Zhao <hongy...@gmail.com> wrote:

> On Wed, 25 Nov 2009 21:02:04 -0600, Ed Morton <morto...@gmail.com>
> wrote:
>
>>So, is there actually any swapping involved or do you just want to save line_a
>>and print it before line_b?
>
> 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
>

awk 'BEGIN{a=b=i=0}/line_a/{a=i;} /line_b/{b=i;} {l[i++]=$0;} END{t=l[b];for(i=0;i<NR;i++){if(i!=b)print l[i];if(i==a)print t;}}' your_file


--
Live like a child, think like the god.

WANG Cong

unread,
Nov 27, 2009, 10:42:27 AM11/27/09
to
On 11/27/09 10:16, Hongyi Zhao <hongy...@gmail.com> wrote:

> On Thu, 26 Nov 2009 13:37:15 -0800 (PST), w_a_x_man
> <w_a_...@yahoo.com> wrote:
>
>>Yes.
>>ruby -i.bak -pe'gsub( "c", "x" )' data
>>
>>This makes a backup file named "data.bak" and replaces
>>each "c" with "x".
>
> Good, thanks again. I want to do the inplace edit without backup file
> generated. What option should I use?

'-i' without anything, the same as 'sed'.

Hongyi Zhao

unread,
Nov 27, 2009, 9:01:14 PM11/27/09
to
On Fri, 27 Nov 2009 23:42:27 +0800, WANG Cong
<xiyou.w...@gmail.com> wrote:

>'-i' without anything, the same as 'sed'.

Does the gets(nil) statement work with '-i' switch? In my case, I
always meet the error like this:

test.rb:9:in `gets': Can't do inplace edit without backup (fatal)
from test.rb:9

Why?

Hongyi Zhao

unread,
Nov 27, 2009, 9:45:57 PM11/27/09
to
On Fri, 27 Nov 2009 23:41:18 +0800, WANG Cong
<xiyou.w...@gmail.com> wrote:

>awk 'BEGIN{a=b=i=0}/line_a/{a=i;} /line_b/{b=i;} {l[i++]=$0;} END{t=l[b];for(i=0;i<NR;i++){if(i!=b)print l[i];if(i==a)print t;}}' your_file

This works smooth, but I want to do the in place/inline edit on the
file. does awk support in place/inline edit just sed's '-i' switch?

Janis Papanagnou

unread,
Nov 27, 2009, 10:24:43 PM11/27/09
to
Hongyi Zhao wrote:
> On Fri, 27 Nov 2009 23:41:18 +0800, WANG Cong
> <xiyou.w...@gmail.com> wrote:
>
>> awk 'BEGIN{a=b=i=0}/line_a/{a=i;} /line_b/{b=i;} {l[i++]=$0;} END{t=l[b];for(i=0;i<NR;i++){if(i!=b)print l[i];if(i==a)print t;}}' your_file
>
> This works smooth, but I want to do the in place/inline edit on the
> file. does awk support in place/inline edit just sed's '-i' switch?

It's rarely an inline edit what sed does; you just don't see the
temporary file.

No, awk has no -i option to hide the temporary file from you.
But you can put the awk call in a shell script if you don't want
to see the temporary.

Janis

>
> Best regards.

WANG Cong

unread,
Nov 28, 2009, 9:44:40 AM11/28/09
to
On 11/28/09 02:01, Hongyi Zhao <hongy...@gmail.com> wrote:

> On Fri, 27 Nov 2009 23:42:27 +0800, WANG Cong
> <xiyou.w...@gmail.com> wrote:
>
>>'-i' without anything, the same as 'sed'.
>
> Does the gets(nil) statement work with '-i' switch? In my case, I
> always meet the error like this:
>
> test.rb:9:in `gets': Can't do inplace edit without backup (fatal)
> from test.rb:9
>
> Why?

Are you using it on Window$? I have never seen such thing on Linux.
If so, you have to provide the backup file for '-i'.

Hongyi Zhao

unread,
Nov 28, 2009, 9:25:55 PM11/28/09
to
On Sat, 28 Nov 2009 14:44:40 +0000, WANG Cong
<xiyou.w...@gmail.com> wrote:

>Are you using it on Window$? I have never seen such thing on Linux.
>If so, you have to provide the backup file for '-i'.

Cygwin in my case.

Best regards.

Michael Paoli

unread,
Nov 30, 2009, 2:21:58 AM11/30/09
to
On Nov 24, 1:34 am, Hongyi Zhao <hongy...@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
> ...

Perhaps not what's desired, but meets the "specification" (and a bit
more). It watches for a (here_comes_line_a) and b (here_comes_line_b)
lines. If a b line is the first a/b line preceeding an a line, it
will
swap them, unless the first a/b line preceeding that b line is an a
line. E.g. an aba sequence wouldn't change to aab, but a bba sequence
would change to bab.

sed -ne '

/^here_comes_line_[ab]$/!{
p
d
}

/^here_comes_line_a$/{
:a
${
p
q
}
N
/\nhere_comes_line_b$/{
p
d
}
/\nhere_comes_line_a$/{
:l
/\n/P
s/^[^\n]*\n//
tl
}
ba
}

/^here_comes_line_b$/{
:b
${
p
q
}
N
/\nhere_comes_line_a$/{
s/^here_comes_line_b\nhere_comes_line_a$/here_comes_line_a
\nhere_comes_line_b/
s/^here_comes_line_b\n\(.*\)\nhere_comes_line_a$/here_comes_line_a\n
\1\nhere_comes_line_b/
p
d
}
/\nhere_comes_line_b$/{
:m
/\n/P
s/^[^\n]*\n//
tm
}
bb
}
'

Rakesh Sharma

unread,
Nov 30, 2009, 5:09:50 AM11/30/09
to
On Nov 24, 2:34 pm, Hongyi Zhao <hongyi.z...@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.

John W. Krahn

unread,
Nov 30, 2009, 8:01:43 AM11/30/09
to

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

Rakesh Sharma

unread,
Dec 1, 2009, 6:42:55 AM12/1/09
to


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

John W. Krahn

unread,
Dec 2, 2009, 5:29:34 AM12/2/09
to
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 W. Krahn

unread,
Dec 2, 2009, 5:23:48 AM12/2/09
to
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 W. Krahn

unread,
Dec 2, 2009, 5:13:37 AM12/2/09
to
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

John W. Krahn

unread,
Dec 2, 2009, 5:26:21 AM12/2/09
to
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 W. Krahn

unread,
Dec 2, 2009, 5:12:15 AM12/2/09
to
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

Rakesh Sharma

unread,
Dec 3, 2009, 3:29:43 AM12/3/09
to
> human stupidity.               -- Damian Conway- Hide quoted text -
>
> - Show quoted text -

Thanks once again John for your masterly explanations.!

Has it ever crossed your mind (or O'Reilly's) to gather your perl-one-
liner solutions from all over comp.unix.shell, comp.perl, etc.
& put them in a book form?

Thanks,
--Rakesh


0 new messages