I have a shell script which copies an xml file and places it a directory. Now once the xml is copied, I perform a sed
operation to replace a tag value with some other value. I am using the following command:
sed "s#ABC-XYZ#DEF-PQR#g" test.xml > test-newfile.xml
The command executes properly but it creates the new xml "test-newfile.xml" with size 0 bytes. So I guess, this command is working but somehow not able to create the new copy of the xml.
The test.xml
is not empty:
-rw-rw-r-- 1 sujeet11 sujeet 0 May 28 23:06 test-newfile.xml
-rw-rw-r-- 1 sujeet11 sujeet 555 May 28 23:04 test.xml
Now here is the interesting part:
If I open the test.xml in vi mode and without making any changes to the xml, if I save it using :wq and then perform the same sed operation, it substitutes the string and creates the newfile copy with the updated string.
Transferring some comments into an answer.
It sounds as if you're missing a newline at the end of the file (and there's only one line of data in the file). When you edit, vim
will add the newline. I was trying that as a possible source of trouble; both GNU sed
and BSD sed
on Mac OS X 10.9.3 are OK with a file consisting of a null byte, 500 x's and no newline (or the same with a newline at the end).
Does the failing test.xml
end with a newline? Does the copy of the file edited with vim
end with a newline? If the one fails and the other succeeds, that is the problem — text files are supposed to end with a newline, and you invoke undefined behaviour if the file does not end with a newline. Many versions of sed
will work anyway; some will not.
Yes, you are right. The failing test.xml
does not end with a new line. Once I edit it with vim
, it ends with a newline. Thanks! How am I going to take care of it? Any other method to append a new line before performing the sed operation?
It might be easiest to add a newline to the end of the file regardless of whether one exists already, maybe using:
echo "" >>test.xml
You can then use:
sed -e 's#ABC-XYZ#DEF-PQR#g' -e '/^$/d' test.xml
to eliminate all empty lines (or -e '${/^$/d;}'
to remove an empty final line in the file), undoing the damage wrought by the echo if the file already ended with a newline.