用另一个文件的竞赛替换或追加文件中的文本块

时间:2012-08-24 15:44:16

标签: bash unix sed awk grep

我有两个文件:

super.conf

someconfig=23;
second line;

#blockbegin
dynamicconfig=12
dynamicconfig2=1323
#blockend

otherconfig=12;

input.conf

newdynamicconfig=12;
anothernewline=1234;

我想运行一个脚本并input.conf替换#blockbegin#blockend行之间的内容。

我已经有了这个:

sed -i -ne '/^#blockbegin/ {p; r input.conf' -e ':a; n; /#blockend/ {p; b}; ba}; p' super.conf

效果很好,但在我更改或删除#blockend中的super.conf行之前,脚本会替换#blockbegin之后的所有行。


此外,我希望脚本替换块,如果super.conf中的块不存在内容为input.confsuper.conf的新块。 它可以通过remove + append来完成,但是如何使用sed或其他unix命令删除块?

3 个答案:

答案 0 :(得分:1)

虽然我不得不质疑这个方案的效用 - 我倾向于支持那些在没有满足期望时大声抱怨而不是像这样松散的系统 - 我相信下面的脚本会做你想要的。

操作理论:它预先读取所有内容,然后一下子全部发出输出。

假设您将文件命名为injector,请将其命名为injector input.conf super.conf

#!/usr/bin/env awk -f
#
# Expects to be called with two files. First is the content to inject,
# second is the file to inject into.

FNR == 1 {
    # This switches from "read replacement content" to "read template"
    # at the boundary between reading the first and second files. This
    # will of course do something suprising if you pass more than two
    # files.
    readReplacement = !readReplacement;
}

# Read a line of replacement content.
readReplacement {
    rCount++;
    replacement[rCount] = $0;
    next;
}

# Read a line of template content.
{
    tCount++;
    template[tCount] = $0;
}

# Note the beginning of the replacement area.
/^#blockbegin$/ {
    beginAt = tCount;
}

# Note the end of the replacement area.
/^#blockend$/ {
    endAt = tCount;
}

# Finished reading everything. Process it all.
END {
    if (beginAt && endAt) {
        # Both beginning and ending markers were found; replace what's
        # in the middle of them.
        emitTemplate(1, beginAt);
        emitReplacement();
        emitTemplate(endAt, tCount);
    } else {
        # Didn't find both markers; just append.
        emitTemplate(1, tCount);
        emitReplacement();
    }
}

# Emit the indicated portion of the template to stdout.
function emitTemplate(from, to) {
    for (i = from; i <= to; i++) {
        print template[i];
    }
}

# Emit the replacement text to stdout.
function emitReplacement() {
    for (i = 1; i <= rCount; i++) {
        print replacement[i];
    }
}

答案 1 :(得分:0)

我写过perl one-liner:

perl -0777lni -e 'BEGIN{open(F,pop(@ARGV))||die;$b="#blockbegin";$e="#blockend";local $/;$d=<F>;close(F);}s|\n$b(.*)$e\n||s;print;print "\n$b\n",$d,"\n$e\n" if eof;' edited.file input.file

参数:

edited.file - 更新文件的路径 input.file - 使用新块内容

的文件路径

脚本首先删除块(如果找到一个匹配),然后用新内容追加新块。

答案 2 :(得分:-1)

你的意思是说

sed '/^#blockbegin/,/#blockend/d' super.conf