0

我正在尝试编写一个执行以下操作的 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>  

我应该如何解决这个问题?我应该逐行阅读,甚至逐个字符阅读吗?

4

3 回答 3

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>
于 2013-09-11T18:20:15.047 回答
1

仅仅因为你不应该使用sed,这里是如何使用sed.

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

对不起。别客气。

于 2013-09-11T18:55:40.710 回答
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

鲁纳斯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 个空格,它仍然会产生统一的输出。

于 2013-09-11T18:23:21.573 回答