awk/perl 인쇄 회문(대괄호 사이에 있지 않은 경우)

awk/perl 인쇄 회문(대괄호 사이에 있지 않은 경우)

한 줄에 하나씩 여러 문자열이 포함된 파일이 있습니다. 나는 회문이 포함되어 있고 회문이 대괄호 사이에 있지 않은 경우에만 문자열을 찾아서 인쇄하고 싶습니다. 예:

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

현재 문자열이 회문인 경우 한 줄을 인쇄하는 한 줄 코드가 있습니다.

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

다음에서 수정됨여기.

나는 sed대괄호 사이의 모든 것을 제거한 다음 나머지 회문을 평가하는 것을 고려하고 있습니다.

한 줄로 이 작업을 수행하는 방법에 대한 다른 아이디어가 있습니까?

답변1

3개 이상의 문자로 구성된 회문을 하나만 제외하고 모두 찾으려면 다음을 수행하십시오 [...].

$ 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자 이상) 회문을 찾으 [...]므로 찾지 못할 수도 있습니다.모두이벤트. 예를 들어 에서는 첫 번째 위치, 세 번째 위치, 두 번째 위치 에서는 ababa검색되지만 첫 번째 위치에서는 검색되지 않습니다.abababababaaba

답변2

당신이 동의한 단 한 줄의 내용은 어떻습니까? 괄호 안에 있는 단어를 필드 구분 기호로 사용하세요.

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
% 

이는 후행 주석이나 기타 입력을 무시하도록 쉽게 조정할 수 있습니다.

관련 정보