根据特定字符串将一个文件的内容插入另一个文件

时间:2013-09-11 18:09:11

标签: linux bash shell

我正在尝试编写一个执行以下操作的bash脚本:

1)读取一个文件(f1.txt)的内容

2)对于以“<”开头但不包含“start”或“item”的每一行,在后面的行中插入第二个文件(f2.txt)的全部内容。此更改必须在原始文件f1.txt

中完成

例如:

f1.txt:

<start>
  <name1>
    <item>
      stuff
    </item>
  </name1>
  <susan>
    <item>
      stuff
    </item>
  </susan>
</start>

f2.txt:

HELLO
WORLD

结果,f1.txt:

<start>
  <name1>
    HELLO
    WORLD
    <item>
      stuff
    </item>
  </name1>
  <susan>
    HELLO
    WORLD
    <item>
      stuff
    </item>
  </susan>
</start>  

我该如何解决这个问题?我应该逐行阅读,还是逐个字符阅读?

3 个答案:

答案 0 :(得分:3)

您可以使用此awk命令:

awk 'NR==FNR {if (a) a=a ORS $0; else a=$0; next}
     /^ *<[^\/]/ && !/<(start|item)>/ {$0=$0 ORS a}1' f2.txt f1.txt
<start>
  <name1>
HELLO
WORLD
    <item>
      stuff
    </item>
  </name1>
  <susan>
HELLO
WORLD
    <item>
      stuff
    </item>
  </susan>
</start>

答案 1 :(得分:1)

你有一个像这样的纯bash脚本解决方案:

#!/bin/bash

readarray -t S < f1.txt
readarray -t R < f2.txt

for A in "${S[@]}"; do
    if [[ $A =~  ^([[:blank:]]*)\<([^/].*)\> ]] && [[ ${BASH_REMATCH[2]} != start && ${BASH_REMATCH[2]} != item ]]; then
        echo "$A"
        for A in ${R[@]}; do
            echo "${BASH_REMATCH[1]}  $A"
        done
    else
        echo "$A"
    fi
done

Runas bash script.sh。要修改f1.txt,请修改for块末尾的最后一行,将输出重定向到它。

done > f1.txt

输出:

<start>
  <name1>
    HELLO
    WORLD
    <item>
      stuff
    </item>
  </name1>
  <susan>
    HELLO
    WORLD
    <item>
      stuff
    </item>
  </susan>
</start>

如果匹配的深度较高,只要缩进为2个空格,它仍会产生统一的输出。

答案 2 :(得分:1)

仅仅因为您不应该使用sed,以下是使用sed的方法。

sed -e '/ *<[^/]/{/\(start\|item\)/!{r f2.txt'$'\n''}}' f1.txt

对不起不客气。