Is it possible to sort a markdown file by level 1 heading? Looking for sed
or similar command line solution
#B
a content of B
#A
b content of A
to...
#A
b content of A
#B
a content of B
Is it possible to sort a markdown file by level 1 heading? Looking for sed
or similar command line solution
#B
a content of B
#A
b content of A
to...
#A
b content of A
#B
a content of B
A perl one-liner, split for readability
perl -0777 -ne '
(undef,@paragraphs) = split /^#(?=[^#])/m;
print map {"#$_"} sort @paragraphs;
' file.md
You'll want to end the file with a blank line, so there's a blank line before #B
. Or you could change
map {"#$_"}
to map {"#$_\n"}
to forcibly insert one.
You can use GNU Awk with PROCINFO["sorted_in"] = "@ind_str_asc"
:
gawk 'BEGIN { PROCINFO["sorted_in"] = "@ind_str_asc"; RS = ""; ORS = "\n\n" }
{ a[$1] = $0 } END { for (i in a) print a[i] }' file
Output:
#A
b content of A
#B
a content of B
Reference:
PROCINFO["sorted_in"] If this element exists in PROCINFO, then its value controls the order in which array elements are traversed in for loops. Supported values are "@ind_str_asc", "@ind_num_asc", "@val_type_asc", "@val_str_asc", "@val_num_asc", "@ind_str_desc", "@ind_num_desc", "@val_type_desc", "@val_str_desc", "@val_num_desc", and "@unsorted". The value can also be the name of any comparison function defined as follows:
you can also use this script to have the sorting on 3 levels instead of just one. It also won't stripe out the content before the first occurence of the first heading.
#!/usr/bin/env perl
local $/;
my $text = <>;
my ($start, @chapters) = split/^#(?=[^#])/m, $text;
print $start;
for (sort @chapters) {
my ($level1, @subchapters) = split/^##(?=[^#])/m;
print "#$level1";
for (sort @subchapters) {
my ($level2, @subsubchapters) = split/^###(?=[^#])/m;
print "##$level2";
print map {"###$_"} sort @subsubchapters;
}
}