ファイルの両方の行が特定のパターンと一致する場合、どのようにリンクしますか?

ファイルの両方の行が特定のパターンと一致する場合、どのようにリンクしますか?

複数の行を含むファイルがありますが、すべて特定のパターンと一致する場合はリンクしたいと思います。

以下を使用して、パターンに合った行を見つけて、次の行を取得できることを知っています。

grep -E -A1 'Pattern' filename

しかし、次の行もパターンと一致するかどうかを確認し、2行をどのようにリンクしますか?

たとえば、次のようなファイルがあります。

Hello
i
am
John
Smith

例示的なパターンは以下の通りである。

'^[A-Z][a-z]+'

したがって、この場合はすべて大文字で始まる行をマージしたいと思います。

私が達成したい結果は次のとおりです。

Hello
i
am 
John Smith

答え1

/^[A-Z][a-z]+/{
  :a
  N
  /\n[A-Z][a-z]+/{
    s/\n/ /
    b a
  }
}

別の名前で保存しjoin.sedて実行してくださいsed -Ef join.sed file

行がパターンと一致する場合は、パターン空間に次の行を追加し、行もパターンに一致する限り、改行を空白に置き換えるループを開始します。

GNU Sedの場合は、1行に縮小できます。

sed -E '/^[A-Z][a-z]+/{:a;N;/\n[A-Z][a-z]+/{s/\n/ /;b a}}' file

join.awkまたは、パターンが次のようになる必要があるAwkスクリプトp

{
    if($0~p)c+=1
    else c=0
    printf "%s%s", (c>1 ? " " : ors), $0
    ors=ORS
}
END{print ""}

実装する: awk -f join.awk p='^[A-Z][a-z]+' file

答え2

sedヌル文字を区切り文字(-z)として使用します。

$ sed -z 's/\([A-Z][a-z]\+\)\n\([A-Z][a-z]\+\)/\1 \2/'
Hello
i
am
John Smith

答え3

Raku(以前のPerl_6)の使用

raku -e 'given lines.join("\n") { S/ $<first>=[<upper><lower>+] \n $<last>=[<upper><lower>+] /$<first> $<last>/.put};'

入力例:

Hello
i
am
John
Smith
goodbye

出力例:

Hello
i
am
John Smith
goodbye

上記は、Perlファミリーの言語であるRakuで書かれたソリューションです。データgivenは の形で Raku に転送されますがlines、 Raku のlines入力自動切り取りルーチンによりデータがjoin折り返されます。やや複雑に見えるかもしれませんが、Rakuのルーチンがlinesデータをゆっくり読み取ることができるという利点があります。つまり、上記のコードはしなければならない高いメモリ効率。

Rakuは、おなじみの演算子(Rakuにもあります)と同じではなくても、同様のS///「非破壊的」演算子を実装します。s///資本事業者にはS利点があります。「元の文字列をそのまま残し、$/(一致変数)の代わりに結果の文字列を返します。」

演算子の一致する(左)半分内でS///名前付きキャプチャ就職してください。正規表現エンジンは最初にそれを検索して[<upper><lower>+]名前付きキャプチャに割り当て、次に$<first>1つ(改行文字)を検索し、\n最後に別の文字を検索して[<upper><lower>+]今回は名前付きキャプチャに割り当てます$<last>。最後に、演算子の置換(右)の半分で、S///2つの名前付きキャプチャが左の$<first> $<last>一致を置き換えるために使用されます。そしてスペースといいえ\n間に線が切れます。

同じタスクを実行する別の方法は次のとおりです。コードは、名前付きキャプチャを省略し、代わりに一致オブジェクト<(\n)>からキャプチャタグ内のコンテンツを除くすべてのアイテムを削除するキャプチャタグを使用します<(…)>。次に、置換から空白\n に置き換えます。

raku -e 'put S/ [<upper><lower>+] <(\n)> [<upper><lower>+] / / given lines.join("\n");'  

[上記のコードは、George\nHerbert\nWalker\nBush4行を3行に縮小します(George Herbert\nWalker\nBush)。行から連続したアイテムをすべて返すには、[<upper><lower>+]この質問を投稿してください。]

https://docs.raku.org/言語/regexes#S///__non-breaking_substitution
https://docs.raku.org/言語/regexes#index-entry-regex__Named_captures-Named_captures
https://raku.org

関連情報