可能であれば(bashで)を使用して解析し、再フォーマットする必要がある大きなファイルがありますsed
。ファイルには、でPATTERN_START
始まり終わる繰り返しシーケンスが含まれていますPATTERN_END
。このシーケンスは、私が変更せずに維持しなければならなかった他のテキストと混在していました。シーケンスには複数のレコードがあります(1から番号が付けられています)。N、どこN1〜12まで可能)レコードは、次の形式の1行で始まる行のセットです。Record i
私1と1の間の整数です。N、別の行()または1行で終わります。レコード長は1行から30行まで可能です。Record (i+1)
PATTERN_END
以下は入力ファイルの一般的な表現です。
無関係なデータ (行が多い場合もあります) ⎤ モード_スタート| 記録1⎤| 1つのデータ記録 ⎤ (最大30行) | (複数回繰り返す) ︙⎦| (最大12レコード) | レコード2 | 2つのデータを記録 ⎦| パターン_END⎦ 無関係なデータ (行が多い場合もあります)
だから、各レコードのすべてのデータ行をPATTERN_START
間にあるレコードに対してのみその行に集計したいと思います。PATTERN_END
Record
誰でも助けることができますか?
以下は、解析する必要があるファイルの例と目的の結果の種類です。
入力する
Blabla
Blabla
PATTERN_OTHER
Record 1 <- record not between PATTERN_START and PATTERN_END tags => do not touch it
Data
Data
PATTERN_END
Blabla
PATTERN_START
Record 1 <- record between PATTERN_START and PATTERN_END tags => to put in one line
Data
Data
Data
Record 2 <- record between PATTERN_START and PATTERN_END tags => to put in one line
Data
Data
Record 3 <- record between PATTERN_START and PATTERN_END tags => to put in one line
Data
Data
Data
Data
PATTERN_END
Blabla
Blabla
Blabla
Blabla
PATTERN_START
Record 1 <- record between PATTERN_START and PATTERN_END tags => to put in one line
Data
Data
Data
PATTERN_END
Blabla
Blabla
PATTERN_OTHER
Record 1 <- record not between PATTERN_START and PATTERN_END tags => do not touch it
Data
Data
Record 2 <- record not between PATTERN_START and PATTERN_END tags => do not touch it
Data
PATTERN_END
Blabla
Blabla
PATTERN_START
Record 1 <- record between PATTERN_START and PATTERN_END tags => to put in one line
Data
Record 2 <- record between PATTERN_START and PATTERN_END tags => to put in one line
Data
Data
Data
PATTERN_END
Blabla
Blabla
出力
Blabla
Blabla
PATTERN_OTHER
Record 1 <- was not between PATTERN_START and PATTERN_END tags => not modified
Data
Data
PATTERN_END
Blabla
PATTERN_START
Record 1 Data Data Data <- record data grouped in one line
Record 2 Data Data <- record data grouped in one line
Record 3 Data Data Data Data <- record data grouped in one line
PATTERN_END
Blabla
Blabla
Blabla
Blabla
PATTERN_START
Record 1 Data Data Data <- record data grouped in one line
PATTERN_END
Blabla
Blabla
PATTERN_OTHER
Record 1 <- was not between PATTERN_START and PATTERN_END tags => not modified
Data
Data
Record 2 <- was not between PATTERN_START and PATTERN_END tags => not modified
Data
PATTERN_END
Blabla
Blabla
PATTERN_START
Record 1 Data <- record data grouped in one line
Record 2 Data Data Data <- record data grouped in one line
PATTERN_END
Blabla
Blabla
ベストアンサー1
これがGNU sedで欲しいものだと思います
sed -n '/^PATTERN_START/,/^PATTERN_END/{
//!{H;/^Record/!{x;s/\n\([^\n]*\)$/ \1/;x}};
/^PATTERN_START/{h};/^PATTERN_END/{x;p;x;p};d
};p' file
説明する
sed -n #Non printing
'/^PATTERN_START/,/^PATTERN_END/{
#If the line falls between these two patterns execute the next block
//!{
#If the previous pattern matched from the line above is not on matched(so skip
the start and end lines), then execute next block
H;
#append the line to the hold buffer, so this appends all lines between
#`/^PATTERN_START/` and `/^PATTERN_END/` not including those.
/^Record/!{
#If the line does not begin with record then execute next block
x;s/\n\([^\n]*\)$/ \1/;x
#Swap current line with pattern buffer holding all our other lines
#up to now.Then remove the last newline. As this only executed when
#record is not matched it just removes the newline from the start
#of `data`.
#The line is then put switched back into the hold buffer.
}
#End of not record block
};
#End of previous pattern match block
/^PATTERN_START/{h};
#If line begins with `PATTERN_START` then the hold buffer is overwritten
#with this line removing all the previous matched lines.
/^PATTERN_END/{x;p;x;p}
#If line begins with `PATTERN_END` the swap in our saved lines, print them,
#then swap back in the PATTERN END line and print that as well.
;d
#Delete all the lines within the range, as we print them explicitly in the
#Pattern end block above
};p' file
# Print everything that's not in the range print, and the name of the file