開始キーワードと終了キーワードの間に行をコピーして貼り付ける方法は?

開始キーワードと終了キーワードの間に行をコピーして貼り付ける方法は?

2つのテキストファイルがあり、あるファイルから別のファイルに複数行をコピーしたいと思います。ファイル1にはパッケージのリストがあり、それをリスト2にコピーしたいと思います。このパッケージのリストはファイル1の先頭にはありませんが、リストの先頭に%packagesタグがあり、最後に%endタグがあります。 %packagesと%endの間のすべての行をファイル1からファイル2にコピーする方法を知りたいです。

答え1

%packages と %end の間のすべての行を file1 から file2 にコピーするには:

awk '$1=="%end" {f=0;next} f{print;next} $1=="%packages" {f=1}' file1 >>file2

この回避策は、%packages行と%end行を削除することです。 (この行も移動するには、以下に簡単な解決策があります。)

awkファイルのすべての行に対して暗黙的に繰り返されるため、上記のコマンドが適用されます。file1このコマンドは、呼び出されたフラグを使用してのfパッケージセクション内にあることを確認しますfile1。パッケージセクションの各行はstdoutとして印刷されますfile2

awk次のコマンドを1つずつ見てみましょう。

  • $1=="%end" {f=0;next}

    このコマンドは、行がで始まることを確認します%end。その場合、フラグは0に設定され、対応する行fにジャンプします。next

  • f{print;next}

    このコマンドはフラグがfゼロでないことを確認します。 0以外の場合は、行を印刷して次の行にジャンプします。

  • $1=="%packages" {f=1}

    このコマンドは、行がで始まることを確認します%packages。もしそうなら、フラグをf1に設定してそれ以降の行を印刷します。

マーカーラインが含まれています:

上記には %packages と %end バーは含まれません。これを含めるには、次のようにします。

awk '/^%packages/,/^%end/ {print}' file1 >>file2

答え2

awkに加えて考慮すべきもう一つの解決策はsedです。

sed -n '/%packages/,/%end/ w file2' file1

出現順に分類:
sed明らかにそれ自体には開口部があります'。これはsedに、この時点から最後まで'すべてがsed自体の引数/コマンドであることを伝えます。それ以降の内容はすべて入力されます(またはリダイレクト>ファイルを使用している場合は出力)。

-n印刷を抑制します。これがない場合、file1 の内容全体が印刷され、一致するテキストが 2 回印刷されます。

/pattern1/,/pattern2/一致させる範囲の制限を定義します。

w fileファイルに書き込みます。最後のパラメータでなければならず、その後にファイル名(または現在のディレクトリにない場合は/ path / to / file)が続きます。

最後に、シングルを閉じた後に'入力ファイルがあります。

最後の2つのメモ:

1. 一部の人々は入力ファイルにリダイレクトを使用するのが好きなので、最終的なコマンドは次のようになります。

sed -n '/%packages/,/%end/ w file2' <file1

利点は、より明確であることです。つまり、入力をどこで受け取るかは明らかです。同様に、次w fileを使用する代わりに、出力を> fileにリダイレクトできます。

sed -n '/%packages/,/%end/ p' <file1 >file2

この場合、p印刷一致を追加します(選択のために-nオーバーライド)。

ただし、sedは複数の入力ファイルで動作できます。

sed -n '/%packages/,/%end/ w file-final' file1 file2 file3

リダイレクトでは、ユーザーがこの機能を無視することがよくあります。

2. 上記の一致には、開始行と終了行が含まれます。 sed は単語レベルではなく行レベルで動作するためです。 1つの解決策は、単により多くのsedにパイプすることです。

sed -n '/%packages/,/%end/ w file2' file1 | sed -e '1d' -e '$d'

次の新機能が導入されました。
-e同じ入力で複数のコマンドを実行できます。一致するパターンを削除して、
1バー番号の一致が機能します
d。最初のコマンドの行番号 1 は
$入力ストリームの終わりです。 sed は単語レベルではなく行レベルで動作するため、最後の行全体が削除されます。

ただし、実際にはグループ化のために中かっこを使用して、単一のsed呼び出しでこれを行うことができます(明確にするためにスクリプトで)。

#!/bin/bash
sed -n '
  /%packages/,/%end/ {
    /%packages/n
    /%end/ !{
      w file2
    }
  }
' file1

ここで(グループ化に加えて)唯一の新しい点は、!一致を否定することです。
/pattern/nパターンで印刷された線を抑制します(-n最初と同じ)。 /pattern/ !パターンと一致しないすべての項目を選択します(逆一致)。しかし、その理由は簡単です。 %end パターンを抑制するために別のアクションをとると、/%end/n範囲を制限するためにこれを抑制し、ファイルは最後まで印刷されます。

答え3

最も理解しやすい:

grep -A 1000 '%packages' xx | grep -B 1000 '%end'

最初の部分は%packages1000行(一致する行を含む)を検索して印刷します。 その後。

パイプの後ろの2番目の部分:%end1000行(一致する行を含む)をすべて検索して印刷します。第二 前に。

ファイルが1000行を超える場合は、1000を大きい数に変更してください。

欲しいならただ開始および終了正規表現を含む検索パターンのみを含む行を一致させます。金利。

grep -A 1000 '^%packages$' xx | grep -B 1000 '^%end$'

一致する行を含めない場合は、別のパイプを追加してください。

grep -A 1000 '^%packages$' xx | grep -B 1000 '^%end$' | grep -v -e '^%packages$' -e '^%end$'

ここでは-e、複数の検索パターンを指定し、-v一致の意味を変更して、一致しない行を選択するために使用できます。

関連情報