行の最長共通プレフィックス

行の最長共通プレフィックス

テキストファイルまたはテキストストリームがある場合は、2行の最も長い共通プレフィックスをどのように決定し、それをbashの標準出力として印刷しますか?最も長いプレフィックスが複数ある場合、どちらが印刷されるかは関係ありません。

たとえば、次のような入力の場合:

abcdef
abc
defgh
abcdeg
defgi

2 行間の最も長い共通接頭辞はabcde(1 行目と 4 行目の間) で、2 番目に長いのはdefg、3 番目はabc... です。

答え1

次のことができます。

<file LC_ALL=C sort |
   sed -n 'N;h;s/^\(.*\).*\n\1.*/\1/p;g;D' |
   awk '{l = length}
        l > max {max = l; s = $0}
        END {print s}'

最も長い共通接頭辞を持つ行が隣接することを保証するバイト間比較(sortCロケール)を使用して入力をソートします。

sed印刷されたBRE逆参照(キャプチャされた\(.*\).*\n\1文字シーケンス\(.*\)の後に任意の数の文字.*、改行文字、および\n以前にキャプチャされたものと同じ文字シーケンス)を使用して、1行\1と次の行の間の最も長い共通プレフィックスを見つけます。

awkその中で最も長いものを探します。 (1つ以上の場合は、入力の最初の項目が選択されるため、語彙順の最初の項目になります。>=代わりに、>最後の項目をインポートするために使用してください。)

最長の共通プレフィックスを探します。数値。それを所有するバイト、3つのコマンドすべてに対してに$LC_ALL設定します。たとえば、UTF-8ロケールでは、との間の最も長い共通プレフィックスで2文字を検索する代わりに3バイトを検索します。性格。CsortStStéphaneStábatSt<0xc3><0xc3>áé

それを所有する拡張文字列クラスタ。たとえば、Steps間にないStéphaneé2つの文字の文字列クラスタとして表示されますe\u0301)を見つけるには、次のようにします。StSteperl

<file LC_ALL=C sort |
  perl -Mopen=locale -ne '
    BEGIN{$prev = <>}
    if ("$prev$_" =~ /^(\X*).*\n\1\b{g}/) {
      $l = length($1);
      if ($l > $max) {$max = $l; $s = $1}
    }
    $prev = $_;
    END{print "$s\n"}'

\X一致する拡張文字列クラスタ\b{g}そして文字素クラスタ境界の拡張(これにはPerl 5.22.1以降が必要です)。

最長の共通接頭辞を探したい場合みんな入力ライン(単に任意のラインではない)2入力行)もともとあなたが尋ねると思ったように、その他のQ&A回答はこちら

関連情報