Eu tenho um arquivo de texto chamado entry.txt
que contém o seguinte:
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Gostaria de dividi-lo em três arquivos de texto: entry1.txt
, entry2.txt
, entry3.txt
. Seu conteúdo é o seguinte.
entry1.txt :
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
entry2.txt :
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
entry3.txt :
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Em outras palavras, o [
caractere indica que um novo arquivo deve começar. As entradas ( [ entry*]
, onde *
é um número inteiro) estão sempre em ordem numérica e são números inteiros consecutivos começando de 1 a N (no meu arquivo de entrada real, N = 200001).
Existe alguma maneira de realizar a divisão automática de arquivos de texto no bash? entry.txt
Na verdade, minha entrada real contém 200.001 entradas.
fonte
match
da entrada:/^\[/ { name=$2 }
deve ser suficiente.[ blahblah blah blah ]
na minha resposta.FS
, por exemplo-F '\\[ | \\]'
.#S x
, onde x é um número 1, 2, ou 3 dígitos. Apenas salvá-los no x.dat seria suficiente. Eu tentei:gawk '/^#S/{match($0, / [0-9]* /, k)} {print >k[1]".dat" }' myFile.txt
e algumas variações disso.gawk '/^#S/{match($0, /^#S (\s+?)([0-9]+)(\s+?)/, k)} {print >k[2]".txt" }' test.txt
fez o truque.2
Porém, não entendo muito bem o número da matriz .Com o csplit do GNU coreutils (Linux não incorporado, Cygwin):
Você terminará com um arquivo vazio extra
entry0.txt
(contendo a parte antes do primeiro cabeçalho).O csplit padrão não possui o
{*}
repetidor indefinido e a-b
opção de especificar o formato do sufixo; portanto, em outros sistemas, você terá que contar primeiro o número de seções e renomear os arquivos de saída posteriormente.fonte
No perl, isso pode ser muito mais simples:
fonte
Aqui está uma breve linha de código awk:
Como é que isso funciona?
/^\[/
corresponde a linhas que começam com um colchete esquerdo e{ofn=$2 ".txt"}
define uma variável para a segunda palavra delimitada por espaços em branco como o nome do arquivo de saída. Então,ofn
é uma condição que é avaliada como verdadeira se a variável estiver definida (fazendo com que as linhas antes do primeiro cabeçalho sejam ignoradas){print > ofn}
redireciona a linha atual para o arquivo especificado.Observe que todos os espaços neste script awk podem ser removidos, se a compactação o deixar feliz.
Observe também que o script acima realmente precisa que os cabeçalhos das seções tenham espaços ao redor e não dentro deles. Se você quiser lidar com cabeçalhos de seção como
[foo]
e[ this that ]
, precisará de um pouco mais de código:Isso usa a
sub()
função do awk para remover espaços à esquerda e à esquerda entre colchetes e espaços em branco. Observe que, de acordo com o comportamento padrão do awk, isso recolhe o espaço em branco (o separador de campos) em um único espaço (ou seja,[ this that ]
é salvo em"this that.txt"
). Se a manutenção do espaço em branco original nos nomes dos arquivos de saída for importante, experimente definir FS.fonte
Isso pode ser feito na linha de comando em python como:
fonte
Essa é uma maneira um tanto grosseira, mas fácil de entender: use
grep -l '[ entry ]' FILENAME
para fazer com que os números das linhas sejam divididos em [entrada]. Use uma combinação da cabeça e cauda para obter as peças certas.Como eu disse; não é bonito, mas é fácil de entender.
fonte
Que tal usar o awk
[
como separador de registros e o espaço como separador de campos. Isso nos fornece facilmente os dados a serem colocados no arquivo como$0
onde ele deve colocar de volta a liderança removida[
e o nome do arquivo como$1
. Só precisamos lidar com o caso especial do 1º registro que está vazio. Isso nos dá:fonte
A resposta de Terdon funciona para mim, mas eu precisava usar o gawk, não o awk. O manual do gawk (procure por 'match (') explica que o argumento do array em match () é uma extensão gawk. Talvez dependa da instalação do Linux e das versões awk / nawk / gawk, mas na minha máquina Ubuntu apenas o gawk executou o excelente responda:
fonte
Aqui está uma solução perl. Este script detecta as
[ entryN ]
linhas e altera o arquivo de saída de acordo, mas não valida, analisa ou processa os dados em cada seção, apenas imprime a linha de entrada no arquivo de saída.fonte
Oi, eu escrevi esse script simples usando ruby para resolver seu problema
você pode usá-lo desta maneira:
eu testei e funciona bem ..
fonte
Eu prefiro a
csplit
opção, mas como alternativa, aqui está uma solução GNU awk:parse.awk
Execute-o assim:
fonte
RT
variável parece ser específica ao Gawk . Esta solução não funciona para mim usando o awk do FreeBSD.