web-dev-qa-db-ja.com

特定の行の直前でファイルの内容を別のファイルに挿入するにはどうすればよいですか?

Sedを使用して特定の行の直前にファイルの内容を別のファイルに挿入するにはどうすればよいですか?

例次のfile1.xmlがあります。

        <field tagRef="376">
        </field>
        <field tagRef="377">
        </field>
        <field tagRef="58">
        </field>
        <group ref="StandardMessageTrailer" required="true"/>
    </fieldList>
</message>

file2.xmlには次のものがあります。

        <field tagRef="9647">
            <description>Offset</description>
        </field>
        <field tagRef="9648">
            <description>Offset Units/Direction</description>
        </field>
        <field tagRef="9646">
            <description>Anchor Price</description>
        </field>

file2の内容を直前にfile1に挿入するにはどうすればよいですか?

<group ref="StandardMessageTrailer" required="true"/>

したがって、次のようになります。

       <field tagRef="376">
        </field>
        <field tagRef="377">
        </field>
        <field tagRef="58">
        </field>
        <field tagRef="9647">
            <description>Offset</description>
        </field>
        <field tagRef="9648">
            <description>Offset Units/Direction</description>
        </field>
        <field tagRef="9646">
            <description>Anchor Price</description>
        </field>
        <group ref="StandardMessageTrailer" required="true"/>
    </fieldList>
</message>

私はその行の後にを使用して挿入する方法を知っています

sed 'group ref="StandardMessageTrailer"/r file2.xml' file1.xml > newfile.xml  

でも前に挿入したいです。

ヘルプに感謝します

20
user301200
f2="$(<file2)"
awk -vf2="$f2" '/StandardMessageTrailer/{print f2;print;next}1' file1 

sedが必要な場合は、ここに1つの方法があります

sed  -e '/StandardMessageTrailer/r file2' -e 'x;$G' file1
20
ghostdog74

2つのパスを作成するのに耐えられる場合は、マーカーを使用できます。

sed '/Standard/i MARKER' file1.xml | sed -e '/MARKER/r file2.xml' -e '/MARKER/d'

ワンパスでそれを行おうとする際の問題は、ファイルの内容を挿入する「r」以外の方法がないことです。「r」は、操作の範囲外で、出力ストリームに挿入します。 、  sedはラインで終了します。したがって、「標準」が最後の行にある場合、それを使用して行うことはすべて、file2が表示されるまでに終了します。

4
Beta

通常、私はこれが好きです:

  1. file1、挿入コンテンツを読み取るファイル
  2. file2、からの読書コンテンツを挿入 file1 の先頭に file2
  3. スクリプトスニペット:

    sed "\$r ${file2}" ${file1} > tmpfile
    mv tmpfile ${file2}

1
Tony

私はさまざまなソリューションを試しましたが、ベータ版のソリューションが役に立ちました。

概要:

  • メインファイルに別のファイルを挿入したかった
  • マーカーを使用して、これらのファイルを挿入する場所を指定したかった

例:
2つのファイルを作成します:

cloud_config.yml:

coreos:
__ETCD2__

etcd2.yml:

  etcd2:
    name:                         __HOSTNAME__
    listen-peer-urls:             http://__IP_PUBLIC__:2380
    listen-client-urls:           http://__IP_PUBLIC__:2379,http://127.0.0.1:2379

次に、そのスクリプトを実行します。

sed '/Standard/i __ETCD2__' cloud_config.yml \
| sed -e "/__ETCD2__/r etcd2.yml" > tmpfile
sed "s|__ETCD2__||g" tmpfile > cloud_config.yml

最後に、私たちはそれを得ました:

coreos:
  etcd2:
    name:                         __HOSTNAME__
    listen-peer-urls:             http://__IP_PUBLIC__:2380
    listen-client-urls:           http://__IP_PUBLIC__:2379,http://127.0.0.1:2379
0

これが私のために働いた解決策でした:

  1. 別の返信で説明されている のようなマーカーの使用

    sed '/StandardMessageTrailer/i MARKER' file1.xml | sed -e '/MARKER/r file2.xml' -e '/MARKER/d'
    
  2. 同様の質問への別の回答で説明されているように 発生したときに行を数える

    LINE_NUMBER_MATCHING=$(sed -n '/StandardMessageTrailer/=' file1.xml) && sed "$((${LINE_NUMBER_MATCHING} - 1))r file2.xml" file1.xml
    
  3. または、同様の質問への別の回答で説明されているようにsed を使用します

    sed $'/StandardMessageTrailer/{e cat file2.xml\n}' file1.xml
    
0
Anthony O.