Issue
I have a Markdown file with the single or increasingly repeated '#' characters, at the start of a line, that marks headings in descending order, i.e. one hash is heading 1 and two hashes is heading 2 etc.
I would like to convert the heading style to the style that uses the '=' character at both the start and end of the line.
(This is across multiple files, hence my desire to use sed.)
Example:
# Heading 1
Some text
## Heading 2
Some more text
### Heading 3
And more
Converts to:
= Heading 1 =
Some text
== Heading 2 ==
Some more text
=== Heading 3 ===
And more
I only want to use sed for this (don't judge me) and I have no problem making the initial match. My challenge is how to add the same number of '=' characters at the end of lines where I match and replace the '#' character(s)?
Footnote: I searched Stackoverflow and other sites and found nothing that covers appending a variable number of characters based on the number of characters in a match. I also asked Chat-GPT but, as I have often found, that just ended in a circular dialog, where I got my own question re-worked and presented as an answer. I therefore plucked up the courage to post here, even though I have been beaten up in the past for not asking the perfect question. Please be kind ;)
Solution
With GNU sed
you could try:
sed -E 's/^#(.*)/=\1 =/;:a;s/^(=*)#(.*)/\1=\2=/;ta'
We first replace any #SOMETHING
line with =SOMETHING =
(s/^#(.*)/=\1 =/
). We need this special treatment to add a space before the trailing =
. Next, we add a loop label (:a
). Then, we replace =...=#SOMETHING
with =...==SOMETHING=
(s/^(=*)#(.*)/\1=\2=/
) and we loop (ta
) as long as there are #
.
Note that technically, if you have lines with a leading mixture of #
and =
, we should be a bit more specific and don't touch them. Example:
sed -E '/^#+\s.*\S/{s/(#+)(.*\S)\s*/\1\2 /;:a;s/^(=*)#(.*)/\1=\2=/;ta}'
Answered By - Renaud Pacalet Answer Checked By - Marie Seifert (WPSolving Admin)