como inserir texto no início de cada parágrafo no bash

como inserir texto no início de cada parágrafo no bash

Tenho um arquivo com vários parágrafos separados por uma linha em branco. Tecnicamente, não são parágrafos, apenas seções de texto separadas por uma linha em branco.

Quero numerar os parágrafos, por assim dizer, inserindo um número na primeira linha de cada linha após uma linha em branco. Então, se meu arquivo disser:

Este é um texto.
Este é mais texto.
Ainda mais texto!

Este é o texto da seção dois.
Mais um pouco de texto.
Você entendeu...

Eu quero fazer isso dizer:

1Este é um texto
isso é mais texto
Ainda mais texto!

2Este é o texto da seção dois.
Mais um pouco de texto.
Você entendeu...

Responder1

Tente isso com comandos internos do bash:

#!/bin/bash

l=1                          # paragraph counter
echo -n $l                   # print paragraph counter without new line
while read x; do             # read current line from file, see last line
  if [[ $x == "" ]]; then    # empty line?
    echo                     # print empty line
    read x                   # read next line from file, see last line
    ((l++))                  # increment paragraph counter
    echo -n $l               # print paragraph counter without new line
  fi
  echo "$x"                  # print current line
done < file

Responder2

Em geral, usar o shell para análise de texto é muito lento e complicado. Aqui estão algumas outras opções:

  1. Perl em "modo parágrafo"

    perl -00pe 's/^/$./' file 
    

    Explicação

    -00Ativa o modo de parágrafo onde "linhas" são definidas por \n\nparágrafos consecutivos, em outras palavras. O s/^/$./substituirá o início da linha ( ^) pelo número da "linha" (parágrafo) atual $.. Diz ao -pPerl para imprimir cada linha do arquivo de entrada após executar o script fornecido -enele.

  2. Estranho

    awk -vRS='\n\n' -vORS='\n\n' '{print NR$0}' file
    

    Explicação

    -vRS='\n\n'define o separador de registros do awk para caracteres de nova linha consecutivos. Como o modo de parágrafo do Perl, isso faz com que ele trate os parágrafos como "linhas". Em seguida, pedimos para imprimir o número da linha atual ( NR) e a "linha" atual $0. Define -vORS=o separador de registro de saída para novas linhas consecutivas, de modo que os parágrafos também sejam separados por linhas em branco na saída. Observe que isso adicionará 2 linhas vazias no final da saída. Para evitar isso, você pode usar head:

    awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2
    

A título de comparação, aqui estão os tempos que as diversas soluções demoraram no meu sistema quando executadas em um arquivo de teste de 10M:

$ time a.sh > /dev/null ## a.sh is Cyrus's solution

real    0m1.419s
user    0m1.308s
sys     0m0.104s

$ time perl -00pe 's/^/$./' file  > /dev/null 

real    0m0.087s
user    0m0.084s
sys     0m0.000s

$ time awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2 >/dev/null

real    0m0.074s
user    0m0.056s
sys     0m0.020s

Como você pode ver acima, as soluções perl e awk são muito mais rápidas que a abordagem shell.

informação relacionada