123
123

Reputation: 11216

Ordering of sed command breaks for unknown reason

Input

File.txt

Start
1
2
3
4
Start
5
6
7
8

Problem

I was messing around with sed to work out different ways to get data from between the Starts.

One script i made was

sed ':2;h;$!N;$b1;/\n.*Start[^\n]*$/{:1;$!x;/5/p;x;s/.*\n//};$!b2;d'

Explanation of script

:2 #A label for the break point

;h #Hold all the lines currently in the pattern buffer, i use this before getting the next line so that it doesn't have the next start.

 ;$!N # Gets the next line for every line except the last
  
 ;$b1 # Breaks to label 1 on the last line. This is to bypass having to see start to enter the block


 ;/\n.*Start[^\n]*$/ # If start is on the last line of pattern buffer then execute the next block

  { #Start of block

  :1 #Label to jump to if end of file

  ;$!x # If not the last line switch in the hold buffer we got which doesn't include the next `Start`.

  ;/5/p # Print if this Start section contains `5`

  ;x #Switch back hold buffer and pattern to get `Start` back

  ;s/.*\n// #Delete everything up to last line of pattern buffer(leaving just `Start`.

  } # End block

  ;$!b2 # If not end of file go back to label at the start

  ;d #Deletes anything left in pattern buffer when we reach the end of the file


  

Outputs

Start
5
6
7
8

Which is correct

But changing the order of $!N;$b1; to $b1;$!N makes the script output nothing.

sed ':2;h;$b1;$!N;/\n.*Start[^\n]*$/{:1;$!x;/5/p;x;s/.*\n//};$!b2;d'

I don't know if I'm missing something obvious, or don't really understand the meaning of $ but it seems to me as though this should make no difference as one command only executes on the last line($) and the other on all other lines, so the ordering shouldn't matter should it?

Any explanations are welcome and if any more info is needed let me know.

Also I DO NOT want a better way of doing this, I just want an explanation of why it is happening.


More Info

Upvotes: 1

Views: 155

Answers (1)

Armali
Armali

Reputation: 19375

$!N;$b1 at the line before last first appends, then branches (as it is now the final line), wheras $b1;$!N doesn't branch, appends, doesn't enter the block. following is $!b2 which isn't taken, followed by d deleting the pattern. (and ending the script, as there is no more input) – Hasturkun

Upvotes: 1

Related Questions