Удалить дубликаты строк в фигурных скобках - PullRequest
1 голос
/ 28 февраля 2020

У меня есть файл, который содержит:

l1_lololo {
    abcdef
    vgjhklfgkchbnvu
    gfuhjfythkjbgftyhkjgyftuihgt6
    deefgik
    abcdef
}

l2_blabla {
    123456
    vgghyfthjfgtrdygfhhbnvu
    gfuhjgvftdyfgvjgyftuihgt6
    deiulouk
    123456
}

Мне нужно проверить текст в фигурных скобках с помощью sed / awk / bash / et c. и удалить дубликаты строк, оставляя только первую повторяющуюся строку в каждой скобке, мне нужно получить это:

l1_lololo {
    abcdef
    vgjhklfgkchbnvu
    gfuhjfythkjbgftyhkjgyftuihgt6
    deefgik
}

l2_blabla {
    123456
    vgghyfthjfgtrdygfhhbnvu
    gfuhjgvftdyfgvjgyftuihgt6
    deiulouk
}

Как я могу это сделать?

Ответы [ 4 ]

4 голосов
/ 28 февраля 2020

Если вы можете гарантировать, что блоки заканчиваются строкой, содержащей только }, это можно сделать так же просто:

awk '/^}$/ {delete a} !a[$0]++' input

Если вам нужно более надежное решение, возможно, просто добавьте несколько пробелов к шаблону, чтобы соответствовать концу блока. Но если вам нужен полный анализатор и вы хотите тщательно подбирать фигурные скобки, awk, вероятно, не подходит для этой задачи.

2 голосов
/ 29 февраля 2020

Если вы открыты для других языков, это действительно легко сделать в tcl благодаря вводу в формате списка tcl, что позволяет использовать его для выполнения всего анализа без каких-либо потенциально регулярных выражений fr agile:

#!/usr/bin/env tclsh
package require Tcl 8.5
foreach {key lst} [read stdin] {
    foreach item $lst { dict set seen $item 1 }
    puts "$key {\n\t[join [dict keys $seen] \n\t]\n}\n"
    unset seen
}

Пример:

$ ./dedup < input.txt
l1_lololo {
        abcdef
        vgjhklfgkchbnvu
        gfuhjfythkjbgftyhkjgyftuihgt6
        deefgik
}

l2_blabla {
        123456
        vgghyfthjfgtrdygfhhbnvu
        gfuhjgvftdyfgvjgyftuihgt6
        deiulouk
}
1 голос
/ 02 марта 2020

Это может работать для вас (GNU sed):

sed -E '/^\S+ \{/{:a;N;s/((\n[^\n]*)(\n.*)*)\2$/\1/;/\n\}$/!ba}' file

Если строка начинается с некоторого текста, за которым следует {, добавьте следующую строку и удалите последнюю строку, если она соответствует предыдущему линия. Повторяйте последнее до строки, содержащей только } и выводите результат.

1 голос
/ 29 февраля 2020

Желаемый результат может быть достигнут с помощью следующего кода (данные хранятся в га sh)

use strict;
use warnings;
use feature 'say';

my $data = do{ local $/; <DATA> };      # read whole data

my %seen;
my %records = $data =~ /(\w+)\s+\{\s*(.*?)\s*\}/sg;     # split into records

while( my($k,$v) = each %records ) {    # for each record split into array
    my @array = map { if( not $seen{$_} ) { $seen{$_} = 1; $_ } } split '\s+', $records{$k};    # store uniq elements
    pop @array;                         # pop out last empty element
    $records{$k} = \@array;             # store array in hash
}

while( my($k,$v) = each %records ) {    # each record
    say "$k = {";                       # output hash key
    say "\t$_" for @{$v};               # output each element of array
    say "}\n";                          # done
}

__DATA__
l1_lololo {
    abcdef
    vgjhklfgkchbnvu
    gfuhjfythkjbgftyhkjgyftuihgt6
    deefgik
    abcdef
}

l2_blabla {
    123456
    vgghyfthjfgtrdygfhhbnvu
    gfuhjgvftdyfgvjgyftuihgt6
    deiulouk
    123456
}

Выход

l1_lololo = {
        abcdef
        vgjhklfgkchbnvu
        gfuhjfythkjbgftyhkjgyftuihgt6
        deefgik
}

l2_blabla = {
        123456
        vgghyfthjfgtrdygfhhbnvu
        gfuhjgvftdyfgvjgyftuihgt6
        deiulouk
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...