I am trying to insert few lines before a specific line in an xml file. Though it's working but the formatting is not retained. Leading whitespaces are getting ignored. I know that we have to use IFS= and i also cross-checked it in the following link besides many others but to no avail. :(
Can anyone please point out the mistake i am committing here?
Preserving leading white space while reading>>writing a file line by line in bash
while read line
do
pattern=keepDependencies
input_file=/home/john/data_file
file_to_change="${backup_dir}/"$line"/config.xml"
while IFS= read -r insert_text
do
sed -i "/$pattern/i $insert_text" $file_to_change
done < "$input_file"
done < days_to_keep_absent
Data File:
[john ~]$ cat data_file
<logRotator>
<daysToKeep>-1</daysToKeep>
<numToKeep>5</numToKeep>
<artifactDaysToKeep>-1</artifactDaysToKeep>
<artifactNumToKeep>-1</artifactNumToKeep>
</logRotator>
config.xml:
<?xml version='1.0' encoding='UTF-8'?>
<project>
<actions/>
<description>I'll clean all the temporary permissions</description>
<keepDependencies>false</keepDependencies>
<properties>
<hudson.security.AuthorizationMatrixProperty>
...
...
Output:
<?xml version='1.0' encoding='UTF-8'?>
<project>
<actions/>
<description>I'll clean all the temporary permissions</description>
<logRotator>
<daysToKeep>-1</daysToKeep>
<numToKeep>5</numToKeep>
<artifactDaysToKeep>-1</artifactDaysToKeep>
<artifactNumToKeep>-1</artifactNumToKeep>
</logRotator>
<keepDependencies>false</keepDependencies>
<properties>
<hudson.security.AuthorizationMatrixProperty>
...
...
It's not read
which is giving you problems. It's sed
.
The usual (and, as far as I know, the only Posix-compatible) way of issuing an i
command is to follow it immediately with a backslash and a newline. The argument consists of the subsequent lines up to the first one not terminated with a backslash:
/pattern/i\
This text is inserted\
So is this text.
GNU sed
allows the inserted text to start on the same line as the i
, following any whitespace. And that is why your whitespace is being deleted.
Try this:
while read line
do
pattern=keepDependencies
input_file=/home/john/data_file
# Note: I fixed quoting in the following line.
file_to_change="$backup_dir/$line/config.xml"
while IFS= read -r insert_text
do
# Note: \\ is reduced to \ because it is inside a double-quoted string
# The newline is inserted directly. So sed sees i\<newline><inserted text>
sed -i "/$pattern/i\\
$insert_text" "$file_to_change"
done < "$input_file"
done < days_to_keep_absent
I find that style a little hard to read, so I would usually do something like this:
ICMD='i\
'
# ...
sed -i "/$pattern/$ICMD$insert_text" "$file_to_change"