Dividir um único arquivo em vários arquivos com base em strings correspondentes no Linux

1

Eu tenho um arquivo com conteúdo semelhante a este:

Arquivo.txt:

661###############20160315###
###########################
###########################
661###############20160316###
###########################
661###############20160317###
###########################

Eu quero dividir este arquivo único em vários arquivos com base na seqüência inicial "661" e data (2016MMDD) e renomear o arquivo dividido como 20160315.txt, 20160316.txt e assim por diante. Por exemplo, cada arquivo dividido terá:

20160315.txt terá:

661###############20160315########
################################
################################

20160316.txt terá:

661###############20160316########
################################

20160317.txt terá:

661###############20160317#######
###############################

Existe um comando do awk que pode fazer isso?

    
por nerd 03.11.2016 / 19:02

2 respostas

5

Tenho certeza de que existe um comando awk que pode fazer isso, não tenho a habilidade necessária em awk para criar uma solução. Enquanto isso, você poderia usar algo assim:

#!/bin/bash

csplit -z tosplit /661/ {*}

for file in xx*; do
    newName=$(egrep -o '2[0-9]{7}' $file)
    mv $file $newName.txt
done
rm -rf xx*

Onde tosplit é esse arquivo (seu arquivo de exemplo):

661###############20160315###
###########################
###########################
661###############20160316###
###########################
661###############20160317###
###########################

Depois de executar este script (no mesmo diretório que o arquivo tosplit ) eu recebo três arquivos:

ls 2016031*
20160315.txt  20160316.txt  20160317.txt

... assim:

cat 20160315.txt 
661###############20160315###
###########################
###########################

cat 20160316.txt 
661###############20160316###
###########################

cat 20160317.txt 
661###############20160317###
###########################

Você pode possivelmente (?) usar csplit para nomear os arquivos também, mas isso também está acima do meu nível de pagamento!

    
por 03.11.2016 / 19:33
2

Com awk algo como

awk '/^661/{f=substr($0,match($0,/2016[0-9]{4}/),8)".txt"}{print>>f}' file.txt

pode funcionar para você.

Basicamente, as partes são:

/^661/{...} # on each line starting with 661

match($0,/2016[0-9]{4}/) # find the index of the date (2016MMDD) in current line

substr($0,match($0,/2016[0-9]{4}/),8) # extract the the date in the current line

f=substr($0,match($0,/2016[0-9]{4}/),8)".txt" # assign it to f and append ".txt"

{print>>f} # redirect the content of the current line into the file named by f

Com uma implementação tradicional de awk , talvez seja necessário substituir as expressões do intervalo por:

awk '/^661/{f=substr($0,match($0,/2016[01][0-9][0-9][0-9]/),8)".txt"}{print>>f}' file.txt

Dependendo do seu caso de uso, você também pode querer alterar o comportamento do redirecionamento , ou seja, print>f vs. print>>f .

    
por 03.11.2016 / 21:45