Linux / Comando csplit: dividir texto por linhas e padrões

csplit divide um arquivo em pontos definidos por números de linha ou por expressões regulares, como um título que marca o início de uma seção. Por exemplo, uma divisão na linha 11 deixa as primeiras 10 linhas na primeira parte e começa a segunda na linha 11. Para partes limitadas por bytes ou por uma quantidade de linhas, consulte o comando split.

Os nomes de saída padrão do GNU csplit são xx00, xx01 e assim por diante. Use uma pasta exclusiva e um prefixo para cada conjunto de partes, porque nomes existentes podem ser sobrescritos. Confira os arquivos e seus limites antes de usá-los como seções de um relatório.

Sintaxe e implementação

csplit [opção...] arquivo_de_entrada padrão...

A linha acima descreve a sintaxe e contém marcadores. O arquivo de entrada vem antes dos padrões de divisão; use - como arquivo para ler a entrada padrão. Confira csplit --version, csplit --help ou man csplit para as opções da implementação instalada.

Os exemplos e os limites descritos foram conferidos com GNU csplit 8.32 no Bash do Git para Windows, usando arquivos locais com finais de linha LF. As expressões entre barras e a repetição '{*}' devem chegar como argumentos ao programa; as aspas simples impedem a interpretação desses trechos pelo shell.

Preparar arquivos e dividir antes da linha 11

Execute o bloco inteiro no Bash, em uma pasta onde possa criar arquivos. Ele prepara todos os dados em um diretório exclusivo e reserva a subpasta sample para o último exercício. Os parênteses executam um subshell, que retorna ao diretório anterior ao terminar. set -eu interrompe este bloco simples diante de falhas não tratadas ou variáveis não definidas.

(
set -eu
labdir=$(mktemp -d ./csplit-demo.XXXXXX)
cd "$labdir"
seq 1 12 > notes.txt
printf 'Intro\nChapter 1\nBody\n' > report.txt
printf 'Preface\nChapter 1\nAlpha\nChapter 2\nBeta\n' > book.txt
mkdir sample
csplit -f part- notes.txt 11
printf 'Arquivos do laboratório: %s\n' "$PWD"
)

part-00 contém os números de 1 a 10, e part-01 contém 11 e 12. A linha indicada não entra na primeira parte: ela inicia a segunda. Csplit mostra 21 e 6, uma contagem de bytes para cada arquivo criado, não seus nomes nem suas quantidades de linhas.

A última linha informa o caminho completo da pasta de prática. Entre nele com cd e aspas para executar os próximos comandos. Os arquivos notes.txt, report.txt e book.txt permanecem disponíveis. Para conferir a divisão numérica, cat part-00 part-01 deve mostrar novamente os números de 1 a 12.

Dividir na linha que corresponde ao padrão

O arquivo report.txt contém Intro, Chapter 1 e Body, uma entrada por linha. O padrão abaixo procura uma linha que comece por Chapter seguido de um espaço.

csplit -f section- report.txt '/^Chapter /'

section-00 contém somente Intro. section-01 contém Chapter 1 e Body: sem um deslocamento adicional, a linha correspondente inicia a nova parte. A expressão regular ^Chapter usa ^ para indicar o início da linha; ela não traduz o texto nem identifica automaticamente outros títulos.

Uma expressão regular é uma regra de busca. Maiúsculas, espaços e âncoras precisam corresponder ao conteúdo real. Um título com espaços antes de Chapter, ou escrito com outras letras, pode exigir outro padrão. Para um teste simples, use primeiro uma amostra que tenha os limites esperados.

Repetir o padrão para separar capítulos

O arquivo book.txt tem um prefácio e dois títulos Chapter. A repetição do GNU csplit '{*}' aplica o padrão anterior tantas vezes quanto possível; ela não representa um novo padrão de texto.

csplit -f chapter- book.txt '/^Chapter /' '{*}'

O resultado é chapter-00 com Preface, chapter-01 com Chapter 1 e Alpha, e chapter-02 com Chapter 2 e Beta. Cada título permanece no começo da sua parte. Sem a repetição, a primeira correspondência divide o arquivo apenas uma vez e o restante fica junto.

Para uma quantidade fixa, '{1}' repete o padrão anterior uma vez além da aplicação inicial. Não confunda essa repetição com uma contagem de arquivos: o conteúdo antes da primeira correspondência e o trecho final também influenciam quantas partes são criadas.

Confira também se os títulos realmente foram encontrados. No GNU 8.32 conferido, um padrão ausente acompanhado de '{*}' pode terminar com status 0 e uma parte com o arquivo inteiro. Sucesso da execução não demonstra, por si só, que houve uma divisão nos capítulos esperados.

Ver o conteúdo e ocultar a contagem de bytes

O exercício abaixo usa a subpasta sample, criada vazia no primeiro bloco, para não sobrescrever part-00 e part-01 da divisão numérica. Execute-o uma vez a partir da pasta principal de prática. -s oculta as contagens de bytes de csplit; o texto mostrado vem dos dois comandos cat.

(
set -eu
cd sample
printf 'one\nTWO\ntwo\n' > sample.txt
csplit -s -f part- sample.txt '/^TWO$/'
cat part-00
cat part-01
)

Dentro de sample, part-00 contém somente one, e part-01 contém TWO e two. A expressão ^TWO$ exige uma linha inteira com TWO em maiúsculas: ^ marca o início e $ o fim. Os dois comandos cat mostram, nesta ordem:

one
TWO
two

Ao sair do subshell, a sessão volta à pasta principal. cat sample/part-00 sample/part-01 mostra novamente o texto completo. A linha TWO continua presente; ela define a fronteira e não é excluída por essa forma do comando.

Tratar partes vazias e escolher os nomes

Se a primeira linha já corresponder ao padrão, a parte anterior a ela pode ter zero bytes. Isso é esperado quando não há prefácio. A opção -z suprime essas partes vazias. Ela não remove as linhas que correspondem aos títulos.

Use -f prefixo para distinguir os conjuntos e -n N para escolher a quantidade de dígitos do sufixo. Por exemplo, -n 3 usa nomes terminados em 000, 001 e assim por diante. Escolha os nomes antes da execução e confira a lista resultante; não reutilize um conjunto de saída de uma tentativa anterior.

Distinguir uma falha do fim normal da repetição

Um número de linha inexistente ou uma correspondência exigida que não aparece pode fazer csplit falhar. No GNU csplit, uma falha normalmente remove os arquivos de saída que essa execução já criou. Com -k, eles são mantidos para inspeção; isso não transforma a tentativa em uma divisão completa ou correta.

Para observar a diferença com os dados da prática, use prefixos novos: csplit -s -f failed- notes.txt 5 99 tenta criar a primeira parte e depois falha porque a linha 99 não existe. Na versão conferida, essa tentativa não deixa as partes criadas. Com csplit -s -k -f kept- notes.txt 5 99, os arquivos já criados ficam disponíveis, mas o status continua indicando falha.

Examine o diagnóstico e consulte echo "$?" imediatamente após uma execução isolada. A ausência de saída com -s não basta para concluir que tudo deu certo. Use um diretório exclusivo porque a limpeza após erro não restaura um arquivo que já existia e foi sobrescrito.

Comparar as partes com a entrada

Para o conjunto de capítulos desta prática, use cat chapter-00 chapter-01 chapter-02 > book-restored.txt e depois cmp book.txt book-restored.txt. O comando cmp não imprime nada e retorna 0 quando os bytes são iguais. Prefira um destino novo, fora do conjunto de partes selecionadas.

Essa recomposição pressupõe que todas as partes corretas estejam na ordem original e que nenhum conteúdo tenha sido descartado. O padrão %expressão% descarta o trecho anterior à correspondência, em vez de gravá-lo em uma parte. Por exemplo, csplit -s -f skip- report.txt '%^Chapter %' deixa somente Chapter 1 e Body no conjunto skip-. Nesse caso, reunir as partes não reproduz a entrada integral. Preserve a entrada e confira se as seções atendem ao objetivo.

Opções principais

Opção Uso
-f prefixo Define o início dos nomes dos arquivos de saída.
-n N Define a quantidade de dígitos do sufixo numérico.
-s Oculta as contagens de bytes; não oculta necessariamente os erros.
-z Suprime arquivos de saída vazios.
-k Mantém os arquivos já criados quando ocorre uma falha.

Pergunta frequente

Quando usar split e quando usar csplit?

Use split para dividir por um tamanho em bytes ou por uma quantidade de linhas. Use csplit para escolher pontos de divisão por números de linha ou por expressões regulares, como títulos de seções. Em ambos, confira as partes, os nomes de saída e a recomposição antes de depender do resultado.

Documentação

Consulte a documentação oficial do GNU csplit para padrões, repetições e tratamento de erros. A página de manual de csplit publicada pelo Debian também reúne as opções; compare-a com a versão instalada.