2

I have two files. The fist file is an existing C/C++ source file (*.cpp). The second is a text file (*.txt) and contains one function. The function is in both files, and it needs to be copied from the second file (*.txt) to the first file (*.cpp). The function is also rather long (890+ lines), so copy/paste is a bit unwieldy.

I have a sed command to capture the function in the first file (*.cpp):

ifile=blake2.cpp.old
ofile=blake2.cpp
ffile=blake2-neon.txt
sed -n '/^static void BLAKE2_NEON_Compress64(/,/^}$/p' < $ifile > $ofile

What I don't know is how to tell sed to replace the text it has captured. I've tried to work through the GNU sed manual, but I'm not having much luck. One of the first things to do is drop the /p.

How do I tell sed to replace the block of text it finds with the text from another file?


I found a similar question at How to replace text between two markers in a file with a section of text from another file? but I don't quite follow whats going on, especially since the question is tagged sed but the answers are provided for ed.


The reason I am trying to script this is: its a port of IA-32 SSE to ARM NEON. I have a script that performs the basic substitutions. After a change, I need to copy the updated function to the source code, scp the code to a device, and then compile it. Lather, rinse, repeat. The manual copy/paste of a 1000 line function at each iteration consumes time better spent on other things.

  • Wouldn't an #include of the .txt file work, if you scp the latter as well? – Stephen Kitt May 09 '16 at 05:08
  • http://stackoverflow.com/questions/16715373/sed-insert-file-content-after-specific-pattern-match try sed "/^static void BLAKE2_NEON_Compress64(/,/^}$/ r $ffile" < $ifile > $ofile and then delete the original line using another sed command – Sundeep May 09 '16 at 05:12
  • Thanks again @spasic - switching from Appl'e sed to gsed fixed the address problem. However, there's something wrong with the suggestion. The source file with the manual copy/paste is 4800 lines long. After the suggestion, its 4276052 lines long. –  May 09 '16 at 05:26
  • what exactly went wrong? see the difference between manual one and one with sed.. maybe the line got matched multiple times? – Sundeep May 09 '16 at 05:43
  • also, check out http://unix.stackexchange.com/questions/20322/replace-string-with-contents-of-a-file-using-sed – Sundeep May 09 '16 at 05:58

1 Answers1

1

Try something like this. Match the start of the function, use the read command r to read in the text file. Then add a command to delete d all lines between the start and end of the function:

sed '
/^static void BLAKE2_NEON_Compress64(/r '"$ffile"'
/^static void BLAKE2_NEON_Compress64(/,/^}$/d
' <"$ifile" >"$ofile"

If the string to replace is on a single line you can try this

uuid='c0e4e6b2-81f4-477c-89a4-7656e58719ce'
sed '/^'"$uuid"'/{
 r '"$ffile"'
 d
}' <"$ifile" >"$ofile"
meuh
  • 51,383
  • I changed the source file to use a 1-line UUID to make it easier on sed. Could you show the sed to read a C++ source file with a UUID in it (normally, this will cause a compile failure), replace the UUID with the text from another file, and write the modified stream to a new C++ source file? It seems like it should be easy (modify your example), but I'm not getting the damn expected results on OS X 10.8. sed keeps modifying the C++ source file with a UUID, rather than writing to a new file. –  May 09 '16 at 09:27
  • I'm not sure how sed can edit a file unless you use -i to edit in place. Perhaps you could edit your original question with your new version. I have edited my answer with what I think you wanted. Note I quoted the filenames this time as otherwise this can cause errors when there are special characters in the filenames. – meuh May 09 '16 at 09:39
  • Yes, its working fine using the UUID. The script had two variables crossed at the end, and it cause the read and write of files in the quasi-wrong order. –  May 09 '16 at 11:40