Разделение одного файла на несколько файлов на основе совпадающих строк в Linux

Разделение одного файла на несколько файлов на основе совпадающих строк в Linux

У меня есть файл, содержимое которого примерно такое:

Файл .txt:

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

Я хочу разделить этот один файл на несколько файлов на основе начальной строки "661" и даты (2016MMDD) и переименовать разделенный файл в 20160315.txt, 20160316.txt и т. д. Например, каждый разделенный файл будет иметь:

20160315.txt будет иметь:

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

20160316.txt будет иметь:

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

20160317.txt будет иметь:

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

Есть ли команда awk, которая может это сделать?

решение1

Я уверен, что есть awkкоманда, которая может это сделать, я не настолько опытен, чтобы awkпридумать решение. В то же время, вы можете использовать что-то вроде этого:

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

Где tosplitнаходится этот файл (ваш пример файла):

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

После запуска этого скрипта (в том же каталоге, что и tosplitфайл) я получаю три файла:

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

...выглядит примерно так:

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

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

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

Вы, возможно(?), csplitтакже можете использовать его для именования файлов, но это тоже выше моих сил!

решение2

С awkчем-то вроде

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

может подойти вам.

В основном это следующие части:

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

При традиционной awkреализации вам, возможно, придется заменитьинтервальные выраженияк:

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

В зависимости от вашего варианта использования вы также можете захотеть изменитьповедение перенаправления, т.е. print>fпротив print>>f.

Связанный контент