Dividir un solo archivo en varios archivos según cadenas coincidentes en Linux

Dividir un solo archivo en varios archivos según cadenas coincidentes en Linux

Tengo un archivo que tiene un contenido similar a este:

Archivo.txt:

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

Quiero dividir este archivo único en varios archivos según la cadena inicial "661" y la fecha (2016MMDD) y cambiar el nombre del archivo dividido a 20160315.txt, 20160316.txt, etc. Por ejemplo, cada archivo dividido tendrá:

20160315.txt tendrá:

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

20160316.txt tendrá:

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

20160317.txt tendrá:

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

¿Existe algún comando awk que pueda hacerlo?

Respuesta1

Estoy seguro de que hay un awkcomando que puede hacer esto, no tengo la habilidad suficiente para awkencontrar una solución. Mientras tanto, podrías usar algo como esto:

#!/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*

¿Dónde tosplitestá este archivo (su archivo de ejemplo)?

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

Después de ejecutar este script (en el mismo directorio que el tosplitarchivo), obtengo tres archivos:

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

...luciendo así:

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

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

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

csplitPosiblemente (?) también puedas usarlo para nombrar los archivos, ¡pero eso también está por encima de mi nivel de pago!

Respuesta2

con awkalgo como

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

podría funcionar para usted.

Básicamente las partes son:

/^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

Con una awkimplementación tradicional es posible que tengas que reemplazar elexpresiones de intervaloa:

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

Dependiendo de su caso de uso, es posible que también desee cambiar elcomportamiento de la redirección, es decir , print>fvs.print>>f

información relacionada