From: Rakesh Sharma on 30 Nov 2009 05:09 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 30 Nov 2009 08:01 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 1 Dec 2009 06:42 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 2 Dec 2009 05:29 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 2 Dec 2009 05:12
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 |