AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79578428
Accepted
Ramanan T
Ramanan T
Asked: 2025-04-17 11:29:00 +0800 CST2025-04-17 11:29:00 +0800 CST 2025-04-17 11:29:00 +0800 CST

Imprimir padrão correspondente em um arquivo junto com linhas correspondentes

  • 772

Em um script complexo que estou usando greppara obter linhas correspondentes usando um arquivo de padrão

Por exemplo: Aqui está o arquivo contendo o texto

$ cat file.txt
abc$(SEQ)asdasd
wwww$(SEQ)asqqqqqq
efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz
klmn$(SEQ)11111111
op$(SEQ)44444444
qrs$(SEQ)777
tuv$(SEQ)mmmmmmmmm
qrs$(SEQ)777444
asdsd777hdhfgjdfasd
wxyzfhdfghdfh

e aqui está o arquivo de padrão

$ cat pattren.txt
444
777
asd

Estou usando o seguinte grepcomando para obter as linhas correspondentes

O

Na linha de comando, consigo ver qual padrão é correspondido, mas não nos logs quando ele é registrado. Portanto, preciso de uma maneira de imprimir a linha correspondida e o padrão que foi correspondido. A saída deve ser algo como isto: Padrão impresso após TAB (ou qualquer formato reconhecível)

abc$(SEQ)asdasd <TAB> asd
efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz  <TAB> asd
op$(SEQ)44444444    <TAB>   444
qrs$(SEQ)777    <TAB>   444
qrs$(SEQ)777444  <TAB>  777444
asdsd777hdhfgjdfasd  <TAB>  asd777 

Posso usar grep com , -omas não consigo combinar os dois (ou seja, com e sem -o).

Não é necessário usar grep, ficarei feliz em usar qualquer outro comando que possa fazer isso.

string
  • 3 3 respostas
  • 58 Views

3 respostas

  • Voted
  1. Best Answer
    markp-fuso
    2025-04-17T12:17:02+08:002025-04-17T12:17:02+08:00

    Uma awkideia:

    awk '
    BEGIN   { sep1 = "\t"; sep2 = "," }                       # predefine our separators; modify as desired
    
    FNR==NR { ptns[$0]; next }                                # 1st file: save each line as a new index in our ptns[] array
    
            { sfx = ""                                        # 2nd file: reset our suffix
    
              for (ptn in ptns)                               # loop through the indices (aka patterns) of the ptns[] array
                  if (index($0,ptn))                          # if the pattern exists in the current line (ie, index() returns a value > 0) then ...
                     sfx = sfx (sfx == "" ? "" : sep2) ptn    # append the pattern to our suffix
    
              if (sfx != "")                                  # if the suffix is not blank then we found at least one match so ...
                 print $0 sep1 sfx                            # print current line and append the suffix
            }
    ' pattern.txt file.txt
    

    Alternativamente, coloque o corpo do awkscript em um arquivo e acesse via awk -f ...:

    $ cat my_grep.awk
    BEGIN   { sep1 = "\t"; sep2 = "," }
    FNR==NR { ptns[$0]; next }
            { sfx = ""
              for (ptn in ptns)
                  if (index($0,ptn))
                     sfx = sfx (sfx == "" ? "" : sep2) ptn
              if (sfx != "")
                 print $0 sep1 sfx
            }
    
    $ awk -f my_grep.awk pattern.txt file.txt
    

    NOTAS:

    • assume que as linhas em patterns.txtnão têm nenhum espaço em branco inicial/final, o que causaria index()falha na chamada
    • (ptn in ptns)não garante a ordem em que os padrões são processados, o que significa que não há garantia da ordem dos padrões quando impressos no final da linha; embora código adicional possa ser adicionado para atender a um requisito de ordem , o OP precisaria fornecer mais detalhes para incluir como lidar com padrões duplicados e/ou sobrepostos (por exemplo, ae ascorresponderia na mesma index()posição, então qual padrão seria considerado a correspondência real?)
    • como index()só encontraremos a 1ª ocorrência de um padrão, e não fazemos nenhuma tentativa de correspondência além dessa primeira correspondência, essa abordagem apenas nos diz que há pelo menos uma correspondência; codificação adicional seria necessária para determinar o número de correspondências, mas também exigiria detalhes adicionais do OP sobre como processar padrões duplicados e/ou sobrepostos (por exemplo, quantas vezes 4e 44correspondem a 44444444?)

    Ambas as abordagens geram:

    abc$(SEQ)asdasd asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz  asd
    op$(SEQ)44444444    444
    qrs$(SEQ)777    777
    qrs$(SEQ)777444 444,777
    asdsd777hdhfgjdfasd asd,777
    
    • 5
  2. phuclv
    2025-04-17T14:55:15+08:002025-04-17T14:55:15+08:00

    Como qualquer formato reconhecível é permitido, a solução mais simples é substituir as sequências ANSI emitidas pelo grep diretamente por qualquer separador que você quiser, como uma tabulação:

    $grep --color=always -f pattern.txt file.txt | \
      sed -E 's/(\x1b\[[0-9;]*[A-Za-z])+/\t/g'
    abc$(SEQ) asd asd
    efg hij$(SEQ) asd asd asd $(SEQ)zzzzzz
    op$(SEQ) 444 444 44
    qrs$(SEQ) 777
    qrs$(SEQ) 777 444
        asd sd 777 hdhfgjdf asd
    

    Também é possível capturar cada correspondência entre a sequência ANSI inicial e final, por exemplo, aqui eu envolvo cada correspondência dentro[]

    $grep --color=always -f pattern.txt file.txt | \
      sed -E -e 's#\x1b\[m#]\t#g'  -e 's#\x1b\[[0-9;]+m#\t[#g'
    abc$(SEQ) [asd] [asd]
    efg hij$(SEQ) [asd] [asd] [asd] $(SEQ)zzzzzz
    op$(SEQ) [444] [444] 44
    qrs$(SEQ) [777]
    qrs$(SEQ) [777] [444]
        [asd] sd [777] hdhfgjdf [asd]
    

    Para imprimir os padrões no final você pode usar algo assim

    $grep --color=always -f pattern.txt file.txt | while read -r line; do
        printf "%s\t=== Patterns: " "$line"
        echo "$line" | perl -nE 'while (/\x1b\[[0-9;]+m(.*?)\x1b\[m/g) {
            print "$1 "; }; print "\n";'
    done
    
    abc$(SEQ)asdasd === Padrões: asd asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz === Padrões: asd asd asd
    op$(SEQ)44444444 === Padrões: 444 444
    qrs$(SEQ)777 === Padrões: 777
    qrs$(SEQ)777444 === Padrões: 777 444
    asdsd777hdhfgjdfasd === Padrões: asd 777 asd
    
    $grep --color=always -f pattern.txt file.txt | while read line; do \
        printf "$line\t=== Patterns: " | sed -E 's/\x1b\[[0-9;]*[A-Za-z]//g'
        echo "$line" | sed -E 's/^.*\x1b\[[0-9;]+m(.+)\x1b\[m/\1/g'
    done
    abc$(SEQ)asdasd === Padrões: asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz === Padrões: asd$(SEQ)zzzzzz
    op$(SEQ)44444444 === Padrões: 44444
    qrs$(SEQ)777 === Padrões: 777
    qrs$(SEQ)777444 === Padrões: 444
    asdsd777hdhfgjdfasd === Padrões: asd
    

    Se você quiser preservar a cor para uso posterior, você também pode fazer isso diretamente

    $ grep --color=always -f pattern.txt file.txt > output.txt
    $ cat output.txt
    
    • 1
  3. Timur Shtatland
    2025-04-18T02:23:02+08:002025-04-18T02:23:02+08:00

    Para fazer isso em Perl, use isto:

    perl -lne '
    BEGIN {
        chomp( @pats = `cat pattern.txt` );
        $pat = join "|", @pats;
    }
    if ( @matches = m{($pat)}g ) {
        %seen = ();
        @uniq = grep !$seen{$_}++, @matches;
        $uniq = join ",", @uniq;
        print "$_\t$uniq";
    }' file.txt
    

    Saída:

    abc$(SEQ)asdasd      asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz      asd
    op$(SEQ)44444444        444
    qrs$(SEQ)777    777
    qrs$(SEQ)777444 777,444
    asdsd777hdhfgjdfasd     asd,777
    

    O "one-liner" do Perl usa estes sinalizadores de linha de comando:
    -e: Diz ao Perl para procurar código em linha, em vez de em um arquivo.
    -n: Faz um loop na entrada, uma linha de cada vez, atribuindo-a $_por padrão.
    -l: Remove o separador de linha de entrada ( "\n"por padrão no *NIX) antes de executar o código em linha e o anexa ao imprimir.

    O regex usa este modificador:
    g: Corresponde ao padrão repetidamente.

    chomp( @pats = `cat pattern.txt` );
    

    A linha acima lê o conteúdo do pattern.txtarquivo em uma matriz @patse remove as quebras de linha ( chomp).

    $pat = join "|", @pats;: Une os padrões em uma única sequência, delimitada pelo operador |(= OR ).
    @matches = m{($pat)}g: compara os padrões repetidamente ( m{...}g) com a linha atual lida de file.txt. Todas as correspondências são armazenadas em uma matriz @matches(que pode conter repetições do mesmo padrão, se ocorrer mais de uma vez).
    if ( @matches = ... ): @matchesavalia TRUEse há pelo menos uma correspondência.
    @uniq = grep !$seen{$_}++, @matches;: Torna as correspondências únicas e as armazena em @uniquma matriz.
    $uniq = join ",", @uniq;: Une as correspondências únicas em uma vírgula e armazena o resultado em uma única sequência $uniq.

    Veja também:

    • perldoc perlrun: como executar o interpretador Perl: opções de linha de comando
    • perldoc perlre: Expressões regulares Perl (regexes)
    • perldoc perlrequick: Início rápido de expressões regulares em Perl
    • 1

relate perguntas

  • Expressões `let` nesta posição são instáveis

  • O Rust sombreia variáveis ​​que não são declaradas novamente?

  • Usando REGEXMATCH para encontrar células com comprimento de string EXATO, não células com palavras compartilhadas e strings diferentes

  • Precisa converter string com valores de lista para tipo de mapa em scala

  • pcase não reconhece correspondências de string

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve