改行文字を含む文字列を置き換える

改行文字を含む文字列を置き換える

シェルを使用してbash次の行を含むファイルから

first "line"
<second>line and so on

1つ以上の項目を毎回次に"line"\n<second>変更したいと思います。other characters

first other characters line and so on

"したがって、文字列を同じ特殊文字に置き換え、<改行文字に置き換える必要があります。

他の答えから検索した後、sedコマンドの右側(したがって文字列other characters)では改行を許可できますが、左側では許可されていません。

どのような方法がありますか(よりこれsedこの結果を得るにはgrep

答え1

まあ、私はいくつかの簡単な方法を考えることができますがgrep(とにかく交換を行いません)またはsed

  1. パール

    変える"line"\n<second>が表示されたら、other characters以下を使用してください。

    $ perl -00pe 's/"line"\n<second>/other characters /g' file
    first other characters line and so on
    

    または、複数の連続した発生を1つとして扱い、"line"\n<second>すべて単一の項目に置き換えるには、次のようにother charactersします。

    perl -00pe 's/(?:"line"\n<second>)+/other characters /g' file
    

    例:

    $ cat file
    first "line"
    <second>"line"
    <second>"line"
    <second>line and so on
    $ perl -00pe 's/(?:"line"\n<second>)+/other characters /g' file
    first other characters line and so on
    

    これ-00により、Perlは「ショートモード」でファイルを読み込みます。つまり、「行」\n\nがと定義され、\n本質的に各段落が 1 行に処理されるという意味です。したがって、交換は改行全体で一致します。

  2. アッ

    $  awk -v RS="\n\n" -v ORS="" '{
          sub(/"line"\n<second>/,"other characters ", $0)
          print;
        }' file 
    first other characters line and so on
    

    基本的なアイデアは同じです。レコード区切り記号(RS)を設定して\n\nファイル全体を削除し、出力レコード区切り文字を空白に設定し(それ以外の場合は追加の改行が印刷されます)、この関数を使用してsub()それを置き換えます。

答え2

ファイル全体を読み、グローバル置換を実行します。

sed -n 'H; ${x; s/"line"\n<second>/other characters /g; p}' <<END
first "line"
<second> line followed by "line"
<second> and last
END
first other characters  line followed by other characters  and last

答え3

3つの異なるsedコマンド:

sed '$!N;s/"[^"]*"\n<[^>]*>/other characters /;P;D'

sed -e :n -e '$!N;s/"[^"]*"\n<[^>]*>/other characters /;tn'

sed -e :n -e '$!N;/"$/{$!bn' -e '};s/"[^"]*"\n<[^>]*>/other characters /g'

3つすべてが基本的なs///代替コマンドに基づいて構築されました。

s/"[^"]*"\n<[^>]*>/other characters /

彼らはまた、最後の行に注意を払うよう努めます。なぜなら、sed出力が極端な場合に変わる傾向があるからです。これが意味するのは、$!最後の行ではなくすべての行のアドレスを一致させることです。!$

また、両方ともextコマンドを使用して、Nパターンスペースの\newline文字に次の入力行を追加します。sedしばらくこの文字を使ってきた人なら誰でも\newline文字に依存する方法を学びます。それを得る唯一の方法は、明示的にそこに置くことです。

3 つすべてのアクションを取る前に、できるだけ少ない入力を読み取ろうとします。アクションをsed実行する前に、入力ファイル全体を読む必要なく、できるだけ早くアクションを実行してください。

すべてそうですが、N3つすべてが異なる再帰方法を持っています。

最初のコマンド

最初のコマンドは非常に単純なN;P;Dループを使用します。これら3つのコマンドはPOSIX準拠のコマンドに組み込まれており、sedお互いをよく補完します。

  • N- 前述のように挿入された改行区切り記号のN後のパターンスペースに追加の入力行を追加します。\n
  • P- p;同様に、Pパターンスペースを印刷しますが、最初に表示される\newline文字のみを印刷します。したがって、次の入力/コマンドが提供されます。

    • printf %s\\n one two | sed '$!N;P;d'
  • sed P印刷のみ可能一つ。しかし...

  • D- 同様にd;Dパターン空間を削除し、別のラインループを開始します。同じではない d、パターン空間で最初に現れるewlineDのみが削除されます。 ewline 文字の後のパターン空間にさらに多くのコンテンツがある\n場合、残りのコンテンツは次の行ループを開始するために使用されます。たとえば、前の例で a を置き換えると、次も印刷されます。\nseddDsedP一つそして二つ

このコマンドは次の行でのみ繰り返されます。欲しくないs///交換ドアを一致させます。置換は追加された改行をs///削除するため、パターンスペースを削除しても何も残りません。\nNsed D

Pおよび/またはを選択的に適用するためにテストを実行できますが、Dこの戦略に適した他のコマンドがあります。これは、一致する連続行のみを処理するように再帰が実装されたためです。部分連続ラインシーケンスマッチングの代替規則両端選択肢はs///うまくいきません。

次の入力が与えられた場合:

first "line"
<second>"line"
<second>"line"
<second>line and so on

...印刷されます...

first other characters "line"
<second>other characters line and so on

しかしそれは扱います

first "line"
second "line"
<second>line

...まさに。

2番目の順序

このコマンドは3番目のコマンドと非常によく似ています。どちらも:branch/ test タグを使用します。(Joseph R.の答えもこれを証明します。ここ)特定の条件が与えられると、再帰的に戻ります。

  • -e :n -e– 移植可能なスクリプトは、ewline または新しいインライン実行文を使用して sedラベル定義を区別します。:\n-e
    • :n- というラベルを定義しますn。あなたはいつでもbnこのコンテンツを使用または再帰することができますtn
  • tntest コマンドは指定されたラベルを返します。(または提供されていない場合は、現在の行サイクルのスクリプトを終了します)s///最後の呼び出し以降にカスタムタグまたは置換項目がある場合は、成功したと見なされtます。

このコマンドは一致する行を繰り返します。sedパターンを次に正常に変更すると、その他の役割、ラベルsedに戻ってもう一度やり直してください。交換が行われない場合は、:nパターンスペースが自動的に印刷され、次のラインサイクルが始まります。s///sed

これは連続したシーケンスをよりよく処理する傾向があります。最後に失敗した場合は、以下を印刷します。

first other characters other characters other characters line and so on

3番目の注文

前述のように、ここのロジックは以前のロジックと非常に似ていますが、テストはより明確です。

  • /"$/bn- これはsedテストです。 ranchコマンドはそのアドレスの関数なので、bewlineが追加され、パターンスペースがまだ二重引用符で終わるまで、ranchは返されませsedb:n\n"

Nとの間にできるだけ少ない作業を行いますb。これにより、sed次の行がルールと一致しないようにするために必要な正確な入力を非常に迅速に収集できます。交換はグローバルフラグをs///使用する点で異なりますg。したがって、必要なすべての交換を一度に実行します。同じ入力が与えられると、このコマンドの出力は前のコマンドと同じです。

答え4

これはバリエーションですグレンの答え連続して複数回発生した場合に動作します(sedGNUのみ)。

sed ':x /"line"/N;s/"line"\n<second>/other characters/;/"line"/bx' your_file

これは:x支店のラベルです。基本的にこれが行うことは、置き換えられた行を確認し、まだ一致する場合はラベル"line"に分岐:xし(これがまさにそれですbx)、バッファに別の行を追加して処理を開始することです。

関連情報