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 / ubuntu / Perguntas / 1176231
Accepted
user2413
user2413
Asked: 2019-09-24 22:26:48 +0800 CST2019-09-24 22:26:48 +0800 CST 2019-09-24 22:26:48 +0800 CST

AWK: acrescenta o número de linhas *à próxima* ocorrência do padrão (em um arquivo enorme)

  • 772

Considere este arquivo:

#!/usr/bin/env bash
cat > example_file.txt <<EOL
TITLE something
some data
some data
some data
TITLE something else
some other data
TITLE some more
some other data
some other data
some other data
TITLE extra info
some more data
some more data
EOL

Eu preciso adicionar uma nova coluna que:

  • conta o número de linhas,
  • volta a 1 após uma ocorrência de /^TITLE/,
  • começa na parte inferior do arquivo e segue para cima,

Basicamente, o resultado deve se parecer com:

TITLE something,4
some data,3
some data,2
some data,1
TITLE something else,2
some other data,1
TITLE some more,4
some other data,3
some other data,2
some other data,1
TITLE extra info,3
some more data,2
some more data,1

PS você pode supor que:

  • o arquivo sempre começa com uma linha correspondente/^TITLE/
  • o arquivo sempre termina com uma linha que não corresponde/^TITLE/
  • não há duas linhas consecutivas correspondentes/^TITLE/

Editar:

Resultados até agora

em um arquivo de 100 MB:

@Yarom

time tac trial.txt | awk 'BEGIN{x=0} {x++;{if ($1 !~/^pattern/) printf "%s,%s\n",$0,x;else if ($1 ~/^pattern/) {printf "%s,%s\n",$0,x;x=0}}}' | tac > trial2.txt
real    0m0,896s

@bac0n

 time awk '{ a[i++]=$0 } END { while (i--) { a[i]=a[i] "," ++j; if (a[i] ~ /^pattern/) { j=0 } }; for (i=0; i<NR; i++) { print a[i] } }' trial.txt > trial2.txt
real    0m0,830s

@olivo:

time awk -v RS='^pattern' -v FS='\n' '
{
  for(i=NF-1;i>0;i--) 
    printf "%s,%d\n",$i,i; 
    printf RT
}' trial.txt > trial2.txt

real    0m2,343s

@steeldriver

 time awk -vRS='\n(^pattern|$)' -F'\n' -vOFS=, '
   NR>1 {$1 = "^pattern" $1} 
   {for(i=1;i<=NF;i++) print $i, NF-i+1}
 ' trial.txt > trial2.txt
real    0m1,889s

usando mawk em vez de awk, recebo:

mawk: program limit exceeded: maximum number of fields size=32767
awk
  • 4 4 respostas
  • 254 Views

4 respostas

  • Voted
  1. Yaron
    2019-09-24T23:37:29+08:002019-09-24T23:37:29+08:00

    Consegui compilar o seguinte one-liner:

    tac so_count.txt | awk 'BEGIN{x=0} {x++;{if ($1 != "TITLE") printf "%s,%s\n",$0,x;else if ($1 == "TITLE") {printf "%s,%s\n",$0,x;x=0}}}' | tac
    

    Vou explicar um pouco mais:

    • tac- inverter a ordem das linhas (gato reverso).
    • awk- se a primeira coluna não for TITLEavançar o contador, se TITLEimprimir a contagem atual e redefinir para 0.
    • tac- inverta de volta.

    Resultados:

    TITLE something,4
    DATA some data,3
    DATA some data,2
    DATA some data,1
    TITLE something else,2
    DATA some other data,1
    TITLE some more,4
    DATA some other data,3
    DATA some other data,2
    DATA some other data,1
    TITLE extra info,3
    DATA some more data,2
    DATA some more data,1
    

    Boa sorte!

    • 2
  2. oliv
    2019-09-25T03:53:57+08:002019-09-25T03:53:57+08:00

    Usando awk:

    awk -v RS='TITLE ' -v FS='\n' '
    {
      for(i=NF-1;i>0;i--) 
        printf "%s,%d\n",$i,i; 
        printf RT
    }' file
    

    Isso depende do separador de registro RSe do separador de campo FSque são definidos para definir o valor inicial correto para o contador i.

    As únicas instruções imprimem cada campo com o contador e o terminador de registro RTassociado a RS.

    Esta solução tem a vantagem de analisar o arquivo apenas uma vez e não requer colocar o arquivo inteiro na memória.

    • 2
  3. Best Answer
    user986805
    2019-09-25T01:16:45+08:002019-09-25T01:16:45+08:00

    exemplo.awk

    #!/bin/awk -f
    
    { a[i++]=$0 } END {
        while (i--) {
            a[i]=a[i] "," ++j
            if (a[i] ~ /^TITLE/) { j=0 }
        }
        for (i in a) { print a[i] }
    }
    

    Exemplo

    awk -f example.awk example.txt
    

    Resultado

    TITLE something,4
    DATA some data,3
    DATA some data,2
    DATA some data,1
    TITLE something else,2
    DATA some other data,1
    TITLE some more,4
    DATA some other data,3
    DATA some other data,2
    DATA some other data,1
    TITLE extra info,3
    DATA some more data,2
    DATA some more data,1
    
    • 1
  4. steeldriver
    2019-09-25T04:01:54+08:002019-09-25T04:01:54+08:00

    Você pode tratar cada bloco como um registro e cada linha como um campo - dessa forma, você pode obter a contagem regressiva por bloco sem reverter o arquivo ou carregar mais de um bloco na memória.

    Como seus blocos são delineados por um cabeçalho em vez de um rodapé, é necessário um pouco de hackers para lidar com o primeiro e o último registros. O melhor que consigo fazer é:

    awk -vRS='\n(TITLE|$)' -F'\n' -vOFS=, '
      NR>1 {$1 = "TITLE" $1} # replace the RS that got stripped off
      {for(i=1;i<=NF;i++) print $i, NF-i+1}
    ' example_file.txt
    

    Isso deve ser válido em ambos gawke mawk. Suspeito que ele funcionará significativamente mais rápido na sobrecarga inferior mawk; gawka velocidade pode ser comparável se você definir a localidade para C/POSIX, ou sejaLC_ALL=C awk '...'

    • 1

relate perguntas

Sidebar

Stats

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

    Existe um comando para listar todos os usuários? Também para adicionar, excluir, modificar usuários, no terminal?

    • 9 respostas
  • Marko Smith

    Como excluir um diretório não vazio no Terminal?

    • 4 respostas
  • Marko Smith

    Como descompactar um arquivo zip do Terminal?

    • 9 respostas
  • Marko Smith

    Como instalo um arquivo .deb por meio da linha de comando?

    • 11 respostas
  • Marko Smith

    Como instalo um arquivo .tar.gz (ou .tar.bz2)?

    • 14 respostas
  • Marko Smith

    Como listar todos os pacotes instalados

    • 24 respostas
  • Martin Hope
    Flimm Como posso usar o docker sem sudo? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    led-Zepp Como faço para salvar a saída do terminal em um arquivo? 2014-02-15 11:49:07 +0800 CST
  • Martin Hope
    ubuntu-nerd Como descompactar um arquivo zip do Terminal? 2011-12-11 20:37:54 +0800 CST
  • Martin Hope
    TheXed Como instalo um arquivo .deb por meio da linha de comando? 2011-05-07 09:40:28 +0800 CST
  • Martin Hope
    Ivan Como listar todos os pacotes instalados 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    David Barry Como determino o tamanho total de um diretório (pasta) na linha de comando? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher "Os seguintes pacotes foram retidos:" Por que e como resolvo isso? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford Como os PPAs podem ser removidos? 2010-07-30 01:09:42 +0800 CST

Hot tag

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

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