0

私は2つのファイルを持っています:

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


さらに、スクリプトでブロックを置き換える、ブロックが存在しない場合は、コンテンツがtosuper.confの新しいブロックを追加します。これはremove+appendで実行できますが、sedまたは他のunixコマンドを使用してブロックを削除するにはどうすればよいですか?input.confsuper.conf

4

3 に答える 3

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];
    }
}
于 2012-08-24T21:52:36.120 に答える
0

私はperlワンライナーを書きました:

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のパス-ブロックの新しいコンテンツを含むファイルへのパス

最初にブロックを削除し(一致するものが1つ見つかった場合)、次に新しいコンテンツを含む新しいブロックを追加します。

于 2012-08-25T00:49:08.677 に答える
-1

あなたが言うことを意味します

sed '/^#blockbegin/,/#blockend/d' super.conf
于 2012-08-24T16:03:43.330 に答える