awk/perl 印刷回文 (角かっこの間にない場合)

awk/perl 印刷回文 (角かっこの間にない場合)

1行に1つずつ複数の文字列を含むファイルがあります。回文が含まれており、回文が角かっこの間にない場合にのみ、文字列を検索して印刷したいと思います。例:

abba[cdef]gh    # print
abcd[effe]gh    # do not print

現在の文字列が回文の場合、1行を印刷する1行コードがあります。

awk 'BEGIN { system("perl -lne \"print if length == 4 && reverse eq \\$_\" " ARGV[1]) }' words.txt

以下で修正ここ

私はsed角かっこの間のすべてを削除し、残りの回文を評価することを検討しています。

一行でこれを行う方法についての他のアイデアはありますか?

答え1

3 つ以上の文字で構成される回文を 1 つだけ除いてすべてを検索するには、次の手順を実行します[...]

$ echo 'cac[ada]abacab' | perl -nle '
    while (/\[.*?\]|(?=(([^][])(?1)\2|[^][]?))./g) {
      print $1 if length $1 >= 3
    }'
cac
aba
bacab
aca

(単一バイト文字を想定し、-Mopen=locale文字のロケール定義を追加します。)

回文マッチングの鍵は再帰正規表現です。回文は、空の文字列、単一の文字、または一致する文字のペアとその間にある他の回文と一致します。つまり((.)(?1)\2|.?)(?1)再帰部分は(の最初の部分と一致しますが、ここでは(およびを除くすべての文字)に()置き換えます。.[^][]][

マッチング時みんなが表示されると、/.../gPerlは最初の発生後に次の発生を検索します。inがある場合は、inを最初に検索してから検索を続けるため、inが見つかりません\[.*?\]|(([^][])(?1)\2|[^][]?)。したがって、ここでは、単一文字()が文字の先頭にある場合、その文字と一致する条件を一致させます。bacababacababaaba(?=(palindrome))..回門その後でキャプチャされます$1。これは、対応する単一文字を検索し続けることを意味します。


厳密に言うと、sをスキップして文字列内のすべての場所で最も長い(3文字以上)回文を見つける[...]ため、見つからない可能性があります。みんなイベント。たとえば、最初の位置、3番目の位置、2番目の位置ではababa検索されますが、最初の位置では検索されません。abababababaaba

答え2

あなたが同意した1行の内容はどうですか?括弧内の単語をフィールド区切り記号として使用します。

perl -F'\[.*?\]' -le 'for $word (@F) {if ($word eq reverse $word) {print; break}}' file

いくつかの極端なケースはここでは考慮されません。

  • 文字列の長さは考慮しません。
  • 回文番号が見つからないようです。以内に単語:単語全体は回文でなければなりません。

答え3

[...]事前にフィルタリングできますが、Lexなどのスキャナ次の行を使用してください。

#!/usr/bin/env perl
use strict;
use warnings;
LINE: while (readline) {    # for each line (files or stdin)
    LEX: {
        # skip any [] or [...] bits
        redo LEX if m{ \G \[ [^\]]* \] }cgx;
        # two or more not-[ not-vertical-whitespace (\r, \n) chars
        if (m{ \G ([^\[\v]{2,}) }cgx) {
            # palindrome? print the whole line
            if ( $1 eq reverse $1 ) {
                print;
                next LINE;
            }
            # may be more to come...
            redo LEX;
        }
        # advance the lexer a single character
        redo LEX if m{ \G . }cgx;
        # oh it's the end of the line as we know it
    }
}

さまざまなエッジ条件の拡張テストケースがあります。

% < input
abba[cdef]gh    # print
abcd[effe]gh    # do not print
[effe]f00f
asdf[]prinirp
a[]b[]edgegde
% perl palin < input
abba[cdef]gh    # print
[effe]f00f
asdf[]prinirp
a[]b[]edgegde
% 

これは、末尾のコメントやその他の入力を無視するように簡単に調整できます。

関連情報