使用IFS =防止前导空格被忽略

时间:2013-12-26 10:10:03

标签: bash sed ifs

我试图在xml文件中的特定行之前插入几行。虽然它可以工作,但格式不会保留。领先的空白被忽略了。我知道我们必须使用IFS =并且除了许多其他链接之外我还在以下链接中进行了交叉检查,但无济于事。 :(

任何人都可以指出我在这里犯的错误吗?

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



数据文件:

[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&apos;ll clean all the temporary permissions</description>
  <keepDependencies>false</keepDependencies>
  <properties>
    <hudson.security.AuthorizationMatrixProperty>
    ...
    ...



输出:

<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description>I&apos;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>
    ...
    ...

2 个答案:

答案 0 :(得分:1)

这不是read给你带来问题的。它是sed

通常(以及据我所知,唯一与Posix兼容的)发出i命令的方法是立即使用反斜杠和换行符跟随它。该参数由后续行组成,直到第一行不以反斜杠结尾:

/pattern/i\
    This text is inserted\
So is this text.

GNU sed允许插入的文本与任何空格之后的i在同一行开始。这就是你的空白被删除的原因。

试试这个:

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

我发现这种风格有点难以阅读,所以我通常会这样做:

ICMD='i\
'

# ...

sed -i "/$pattern/$ICMD$insert_text" "$file_to_change"

答案 1 :(得分:0)

这是read(以及许多其他shell函数)的一个特性。

你可以解决它:只需在文件前加一个字符(例如:“|”),然后在输出行时取出它

我将重新使用你的算法而不检查它(你说它确实做了你需要的,除了缺少前导空格):

while循环变为:

sed -e 's/^/|/' < "${input_file}" > "${input_file}_modified"
while IFS= read -r insert_text
do
    sed -i "/$pattern/i $( echo "$insert_text" | sed -e 's/^|//' )" $file_to_change
done < "${input_file}_modified"

希望这有帮助