3

I have a file of several sections, each section start with specific title but all of them ending with the same string, I want to sort the file sections according to the titles without sorting the content of each section (i.e. take the whole section as one block) there is also a blank line between each two section, to clarify the idea if the input is as

string5
z
y
x
string

string2
x
z
y
f
string

the desired output would be as

string2
x
z
y
f
string

string5
z
y
x
string
3
  • What are the actual values of string, string2 and string5, and may they occur as part of the x, z, etc.? Are any of the lines within a section empty? Are you sorting on the 2 and 5 in string2 and string5, or on the whole string?
    – Kusalananda
    Jun 18 '20 at 6:46
  • string2 and string5 are titles containg alot of words strating with R01, R02, R03 ... etc, while the end of each section "string" is just a word Jun 18 '20 at 6:50
  • @MohsenEl-Tahawy please consider to read What should I do when someone answers my question? as it applies on all your questions asked. Jun 18 '20 at 8:42
4

Using GNU sed and sort:

sed 's/^$/\x0/g' file | sort -z | tr '\0' '\n'
  • Put null character in empty line
  • sort using null character as delimiter ( -z)
  • finally replace null delimiter with new line using tr.
  • to remove empty lines in first and last line of the output, you may add | sed '1{/^$/d};${/^$/d}'

Output:

string2
x
z
y
f
string

string5
z
y
x
string

(maybe someone can help making \x0 work for non-GNU sed, related Question)

4
  • this just add x0 in the blank line keeping the rest as it is Jun 18 '20 at 7:07
  • 1
    interesting, maybe a GNU vs non-GNU thing again o0
    – pLumo
    Jun 18 '20 at 7:09
  • yep was related to GNU vs non-GNU issue Jun 18 '20 at 7:13
  • this adds two empty lines between blocks. for \x0 if you change to \o0 might be compatible. Jun 18 '20 at 7:33
3

Using GNU awk in paragraph mode and sort the array's values in string mode then print:

awk -v RS= '{ seen[NR]=$0 }
END { PROCINFO["sorted_in"]="@val_str_asc";
      for (block in seen) {print sep seen[block]; sep=ORS}
}' infile
2
  • That removes duplicate records which is not part of the requirements. Jun 18 '20 at 16:47
  • @StéphaneChazelas good catch, fixed that; thanks Jun 18 '20 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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