awk/perl print palindrome если не между скобками

Используйте парсер JSON для анализа JSON, например jq :

$ jq '.quotes.USDEUR' file.json 
0.918695

0
15.09.2018, 21:16
3 ответа

Чтобы найти все¹ палиндромы из 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 ищет следующее вхождение после конца первого, поэтому, если бы у нас было \[.*?\]|(([^][])(?1)\2|[^][]?), мы бы не нашли bacabв abacab. ] потому что он сначала найдет aba, а затем возобновит поиск после этого aba. Поэтому здесь вместо этого мы сопоставляем (?=(palindrome))., который соответствует одному символу (.), при условии, что он находится в начале палиндрома , который затем фиксируется в $1. Это означает, что мы продолжаем поиск после этого единственного символа.


¹ Строго говоря, он находит самый длинный (из 3 или более символов )палиндромов в каждой позиции строки, пропуская [...]s, поэтому он может не найти все палиндромы. происшествия. Например, в ababaбудет найдено ababaв первой позиции, babв третьей позиции, abaво второй позиции, но не abaв первой позиции.

1
28.01.2020, 02:31

Хотя [...]можно было бы отфильтровать заранее, может быть более разумным использовать 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
% 

Это можно легко адаптировать для игнорирования завершающих комментариев или других подобных входных данных.

0
28.01.2020, 02:31

Как насчет одного -вкладыша? Используйте слово в квадратных скобках в качестве разделителя полей:

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

Пара крайних случаев, здесь не рассмотренных:

  • Длина строки не учитывается
  • Невозможно найти палиндром внутри слова :все слово должно быть палиндромом.
1
28.01.2020, 02:31

Теги

Похожие вопросы