Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'd like to rearrange the content of a file on a per line basis (see below), ideally without using Perl or Python (I'm not allowed to... Don't ask.)

The input file contains unordered header lines and lines with backup operation results. The output files should contain the lines ordered as shown below.

Original file:

Completed Backups
Backups with Warnings
Failed Backups
Server A backup was completed with warnings
Server B backup was successful
Server C backup failed
Server D backup was completed with warnings

End result:

Completed Backups
Server B backup was successful
Backups with Warnings
Server A backup was completed with warnings
Server D backup was completed with warnings
Failed Backups
Server C backup failed
share|improve this question
    
It is not clear at all based on which key you want to arrange the lines. Please describe. The example you provide is the actual file content or description of the content. If it is just a description how does the content look like? What did you already try? –  pabouk Oct 17 '13 at 13:08
    
I'm sorry but I don't know what you mean by "key"... This is the actual content (or very close to it) of the file. The first 3 lines are always at the beginning of the file. I would like all the successful backups lines to be listed under the "Completed Backups" line at the beginning and the "completed with warning" lines to be listed under "Backup with warnings" and so on. I didn't try much because I have absolutely no idea on how to do this, at first, I thought sed could do this but I can't figure it out. –  VikJES Oct 17 '13 at 13:46

2 Answers 2

Malicious grep abuse ahoy. My original script relied on the fact that grep is case sensitive, and that your text is oddly cased, and these cases are unique. I've done a second varient (you can see the old one in the edit trail) which uses a bigger chunk of the lines you need rearranged. Doing it 'properly' would likely end up being faster, since this runs through your entire text file for each grep command - for a big file, this means 6 cycles through it to reorganise it.

This should work with some minor mods on windows or linux, or simply copy pasted. This assumes your source file is called original.txt, and your output is new.txt. You could probably sort the grepped out lines if you need them alphabetical. >> appends to a new line

 #! /bin/sh

    grep "Completed Backups" original.txt >> new.txt
    grep "backup was successful" original.txt >> new.txt
    grep "Backups with Warnings" original.txt >> new.txt
    grep "backup was completed with warnings" original.txt >> new.txt
    grep "Failed Backups"  original.txt >> new.txt
    grep "backup failed" original.txt >> new.txt

I'd probably wait for the proper sed or awk based answer if I was you. I'd also experiment with larger subsets of your strings

share|improve this answer

Unfortunately sed or awk will not help here much because the easiest way of the lines reordering is to process the input in multiple passes as Journeyman Geek showed.

Here is just a slightly different alternative which opens the output file just once. Also another approach is in the headers, here they are re-created instead of transferring them from the source.

#!/bin/sh

output=new.txt
input=original.txt

{
  echo "Completed Backups"
  grep "Server .* backup was successful" < "$input"

  echo "Backups with Warnings"
  grep "Server .* backup was completed with warnings" < "$input"

  echo "Failed Backups"
  grep "Server .* backup failed" < "$input"
} > "$output"

As an alternative to specifying the input and output in the script you can read them from the command line:

output="$1"
input="$2"
share|improve this answer
    
just for curiosity's sake, how does this open the output file only once? I think you might have missed the 'title' lines as well. It does look more like 'proper' bash than my answer XD –  Journeyman Geek Oct 22 '13 at 1:17
    
The redirection > "$output" at the end is performed only once and is valid for the whole { ... } block so the output file is opened only once. Another alternative could be to put exec > "$output" to the beginning. In your script the output file is opened repeatedly with every stdout redirection. --- I have omitted the title lines intentionally: "they are re-created instead of transferred from the source" –  pabouk Oct 22 '13 at 1:33
    
ahh, I see. Kind of missed that for some reason –  Journeyman Geek Oct 22 '13 at 2:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.