0

I have the following file, CHANGELOG.rst:

some text
=========

header
------

* list
* list

header
------

* list

I need to add an entry to this file, right after the file's title, so that the updated file will look as the following:

some text
=========

new header
----------

* new list

header
------

* list
* list

header
------

* list

I add that the

new header
----------

* new list

part is already present in a $CHANGES variable.

I know this can be done with sed but I have no idea how to tackle it.

PersianGulf
  • 2,845
  • 6
  • 47
  • 67
linkyndy
  • 17,038
  • 20
  • 114
  • 194

6 Answers6

3

With sed:

sed -i '/PATTERN/a  Line which you want to append' filename

-i is for in-place subsitution

For your example:

sed -i "/=========/a ${CHANGES}" file

some text
=========

new header
----------

* new list

header
------

* list
* list

header
------

* list
Amit
  • 19,780
  • 6
  • 46
  • 54
  • Looks okay. But can you explain a bit more the use of curly braces and single/double quotes around the `$CHANGES` variable? – linkyndy Mar 05 '14 at 14:41
  • @AndreiHorak Curly braces are not necessary but advisable. Double quotes are for variable expansion in sed. I have updated the answer. – Amit Mar 05 '14 at 14:45
  • Alright. However, I am given this error: `sed: -e expression #1, char 147: unknown command: *'`. I believe it's trying to use the contents of `$CHANGES` as some sort of commands, not as plain strings. – linkyndy Mar 05 '14 at 14:53
  • Its because you have `*` in the CHANGES variable. You can disable globbing with `set -f` before you run the sed command and enable it with `set +f` once you are done. – Amit Mar 05 '14 at 14:57
  • It doesn't work, it gives me the same error. Also, isn't there another solution for this, without explicitly setting/unsetting things? – linkyndy Mar 06 '14 at 10:05
1

I wouldn't use sed to inject a value into a text file. I'd use ed.

ed file <<EOF
4i
$yourtext
.
w
EOF

This says,

  1. "start inserting at the fourth line"
  2. insert "$yourtext"
  3. stop inserting
  4. write.
kojiro
  • 74,557
  • 19
  • 143
  • 201
1

Use below if you want to ensure you do this for the first occurrence only:

CHANGES="line1\nline2"
sed -i "0,/\(^=\+$\)/s//\1\n${CHANGES}/" filename
Timmah
  • 2,001
  • 19
  • 18
  • Can you explain what the `0,` and `\1` do? – linkyndy Mar 06 '14 at 10:08
  • 1
    0 means match up-to first occurrence, ie. it wont do multiple replacements, and \1 places the contents of the 1st group between the escaped () of the regex into the substitute part. In your case we're matching lines starting with one or more =. So we substitute \1 with the matched =. More info [here](http://www.grymoire.com/Unix/Sed.html#uh-4) – Timmah Mar 06 '14 at 11:57
  • Okay, it makes sense, But it gives me the following error: `sed: -e expression #1, char 156: unterminated 's' command`. – linkyndy Mar 06 '14 at 12:09
  • what version of sed are you using? This works on GNU sed version 4.2.1 – Timmah Mar 06 '14 at 14:09
  • It's the same, `GNU sed version 4.2.1`. – linkyndy Mar 06 '14 at 14:21
0

Here is my ugly solution using grep:

grep -B100000 "=========" CHANGELOG.rst > new.txt
echo >> new.txt
echo "new header" >> new.txt
echo "----------" >> new.txt
echo >> new.txt
echo "\* new list" >> new.txt
echo >> new.txt
grep -A100000 "=========" CHANGELOG.rst >> new.txt

grep -A gets the lines after the matching string, and grep -B gets the lines after. It only works if the matching string where you want to split the file exists only once.

philshem
  • 24,761
  • 8
  • 61
  • 127
0
sed '/^header/ i\
your content like New Header\
and his content
' YourFile

but this occur at every header

specificaly (as requested)

sed '/^header/ i\
new header\
----------\
\
* new list\

' YourFile
NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43
  • I needed the `sed` for my specific case, not in general. Would appreciate if you could adapt your example to fit my question :) – linkyndy Mar 06 '14 at 10:09
  • I already have the contents which need to be inserted in a variable. Also, what header are you talking about? – linkyndy Mar 06 '14 at 14:19
  • see reply in your other post (http://stackoverflow.com/questions/22227122/dont-treat-variable-content-as-special-characters-in-sed) – NeronLeVelu Mar 06 '14 at 15:23
0

I was able to find a solution to my problem in this stackoverflow answer.

Thanks to @mklement0, the code is:

sed -i "4 i\
${CHANGES//$'\n'/\\$'\n'}" ./CHANGELOG.rst
Community
  • 1
  • 1
linkyndy
  • 17,038
  • 20
  • 114
  • 194