5

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
2
  • 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, 2020 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, 2020 at 6:50

3 Answers 3

8

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)

6
  • this just add x0 in the blank line keeping the rest as it is Jun 18, 2020 at 7:07
  • 1
    interesting, maybe a GNU vs non-GNU thing again o0
    – pLumo
    Jun 18, 2020 at 7:09
  • yep was related to GNU vs non-GNU issue Jun 18, 2020 at 7:13
  • this adds two empty lines between blocks. for \x0 if you change to \o0 might be compatible. Jun 18, 2020 at 7:33
  • On OS X, if you want to work around the unsupported \x0 problem, you can install GNU utils e.g. via Homebrew, and use gsed instead of sed. Feb 3, 2022 at 17:16
5

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
0
1

With perl:

perl -l -00 -e '
  chomp(@paragraphs = <>);
  print join "\n\n", sort @paragraphs' your-file

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .