Linux で一致する文字列に基づいて 1 つのファイルを複数のファイルに分割する

Linux で一致する文字列に基づいて 1 つのファイルを複数のファイルに分割する

次のような内容のファイルがあります:

ファイル.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)、次の 3 つのファイルが生成されます。

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>fprint>>f

関連情報