I have a markdown file that consists of many different headings, I am writing a CI script that modifies one of the section with every push to the repo. My README.md is as follows,


# Title
....some text...
## Heading 1
...some text...

## Heading 2 
...some text....

## Structure
 ├ first-dir
     ┬  first-sub-dir

 ├ second-dir
     ┬  second-sub-dir-1
     ├  second-sub-dir-2

## Heading 3 
...some text....

I wanted to modify the Structure section with the output of the command tree -d -L 2 -n using sed. I tried using

var=$(tree -d -L 2 -n)
sed -i -E "s/## Structure\n<pre>\n(.|\n)*?<\/pre>/## Structure\n<pre>\n ${var} \n<\/pre>/g" README.md

but it was not working properly. I read about command substitution in sed but I wasn't able to understand it properly. Any help regarding this with sed or awk will be beneficial.

awk '
/^<\/pre>$/             {flag=0}
/^## Structure$/        {print; getline; print
                        system("tree -d -L 2 -n")
!flag' <<<$(<file) >file

<<<$(<file) >file - a kind of custom buffer (does not work in all shells). It is possible to replace with a temporary file: file >tmp

A more complex way, I cite just for example:

sed -i '/^## Structure/!b
s/.*/tree -d -L 2 -n/e
G' file

/^## Structure/!b - All lines that do not match the pattern are ignored by the script. And are displayed unchanged. As soon as a pattern is encountered, the following script starts running.
N - Append the next line of input into the pattern space(working buffer). As a result, we have - ## Structure\n<pre>
h - Copy pattern space to hold space (spare buffer).
:1 - Put a mark for the jump.
N - Append the next line. We get in the working buffer - ## Structure\n<pre>\n┬
/<\/pre>$/!b1 - If the end of the line in the working buffer does not match the pattern, then we return to label :1 and add each cycle the next line until line </pre> is added.
s/.*\n// - Then we delete everything in the working buffer except the last line </pre>.
x - We change the contents of the buffers among themselves so that the line appears in the working buffer - ## Structure\n<pre>. And in the spare buffer there is a line - </pre>
p - Printing the contents of the working buffer ## Structure\n<pre>
s/.*/tree -d -L 2 -n/e - We replace the contents of the buffer with the shell command and execute it.
G - Append the contents </pre> of the spare buffer to the working one - append to the output shell command. The content is printed and the job returns to the beginning of the script. The next line after </pre> is read into the working buffer. And since there are no more lines in the file matching pattern /^## Structure/!b, the remaining lines are also displayed unchanged as first.

  • Hello, can you explain the sed expression that you have wrote? Jul 7 at 17:12

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.