この素晴らしいコミュニティは、情報行を並べ替えるための以下のスクリプトを提供しました。
開始{
FS=":"
PROCINFO["sorted_in"]="@val_str_asc"
}/./ {
値[$1]=$0
}/^$/ {
asort(values)
for (値の要素)
印刷値 [要素]
印刷 ""
値を削除
}終了{
asort(value)
for (値の要素)
print value[element]
}
各ブロックはアルファベット順に並べられ、元の意図したとおりに動作します(下記参照)。 sessionStartTimeに基づいて、これらのすべてのデータチャンク(各チャンク間の物理スペースを含む)をソートするように求められました。私はこれがはるかに難しいと思いました。なぜなら、それぞれの8行ブロックを一緒に接着する必要があるからです。
cabLoginID: 0557CAWG0FP27K31JG7Q
ログイン: john
memoryInfo: jsHeapSizeLimit: 2181038080
セッション: cabSessionID: 05P2R3PJGKG2Y2XE4NCZ
セッション開始時間: 2018-10-18T13:03:00.973Z
合計 JSHeapSize: 36675584
JSHeapSize 使用: 29721040
userAgent: Mozilla/5.0cabLoginID: 05P4X6K6GFPJ7K31EJ7H
ログイン: bob
メモリ情報: jsHeapSizeLimit: 2181038080
セッション: cabSessionID: 0536XLJPG7BJXRN42A0F
セッション開始時間: 2018-10-11T11:37:28.195Z
合計 JSHeapSize: 54501376
JSHeapSize 使用: 35478968
userAgent: Mozilla/5.0cabLoginID:053XCDTF8D4J6PD3BG8PLogin
:jack
memoryInfo:jsHeapSizeLimit:2217857988
セッション:cabSessionID:052FPBP6Q6X2XGERWHBT
セッション開始時間: 2018-10-01T01:04:10.899Z
合計 JSHeapSize: 42358792
使用 JSHeapSize: 36482584
userAgent: Mozilla/5.0
望ましい結果:
cabLoginID:053XCDTF8D4J6PD3BG8PLogin
:jack
memoryInfo:jsHeapSizeLimit:2217857988
セッション:cabSessionID:052FPBP6Q6X2XGERWHBT
セッション開始時間: 2018-10-01T01:04:10.899Z
合計 JSHeapSize: 42358792
使用 JSHeapSize: 36482584
userAgent: Mozilla/5.0cabLoginID: 05P4X6K6GFPJ7K31EJ7H
ログイン: bob
メモリ情報: jsHeapSizeLimit: 2181038080
セッション: cabSessionID: 0536XLJPG7BJXRN42A0F
セッション開始時間: 2018-10-11T11:37:28.195Z
合計 JSHeapSize: 54501376
JSHeapSize 使用: 35478968
userAgent: Mozilla/5.0cabLoginID: 0557CAWG0FP27K31JG7Q
ログイン: john
memoryInfo: jsHeapSizeLimit: 2181038080
セッション: cabSessionID: 05P2R3PJGKG2Y2XE4NCZ
セッション開始時間: 2018-10-18T13:03:00.973Z
合計 JSHeapSize: 36675584
JSHeapSize 使用: 29721040
userAgent: Mozilla/5.0
答え1
タイムスタンプがそのロケールで語彙的にソートされており、GNU Awkバージョン4.0以降が提供されているとします。
gawk -vRS= '
match($0,/sessionStartTime:([^[:space:]]*)/,m) {
a[m[1]] = $0
}
END {
PROCINFO["sorted_in"] = "@ind_str_asc"
for (i in a) print a[i] "\n"
}' file
Perlでも同様の方法:
perl -00 -lne '
$h{$1} = $_ if /sessionStartTime:(\S*)/
}{
for $k (sort keys %h) {print $h{$k}}
' file
答え2
これがトリックを行うようです。近いうちにもう少し読みやすいバージョンを投稿してみましょう。
$ perl -e 'while(<>){next if /^$/;push @a,$_;if(/sessionStartTime/){$k=$_}if($#a==7){$v{$k}=[@a];undef @a}}for $x(sort keys %v){for $i (0..7){print $v{$x}[$i]}print "\n"}' <input >output
よりクリーンで読みやすいバージョンです。機能は同じです。
perl -e 'while(<>) {
# skip any blank lines
next if /^$/;
# add line to array a
push @a,$_;
# if line holds our key value, store it
if(/sessionStartTime/) {
$k=$_;
}
# if we've got all 8 lines, store it in a hash, keyed on our sessionStartTime
if($#a==7) {
$v{$k}=[@a];
undef @a;
}
}
# After reaching end of file, process each key and print its 8 lines
for $x (sort keys %v) {
for $i (0..7) {
print $v{$x}[$i];
}
print "\n";
}' <input >output
答え3
バッシュから:
declare -a LINES
declare -A BLOCKS
IFS=$'\n'
addToBlocks() {
if [ "$EPOCH" ]
then
BLOCKS["$EPOCH"]="${LINES[*]}"
else
echo "No sessionStartTime line for this block."
fi
}
while read LINE
do
SSTIME="${LINE/sessionStartTime:}"
[ "${SSTIME}" != "$LINE" ] && EPOCH="$( date +%s -d "${SSTIME%Z}" )"
if [ "${LINE// }" == "" ]
then
addToBlocks
LINES=()
EPOCH=""
else
LINES+=("${LINE}")
fi
done
addToBlocks
for TIME in $( echo "${!BLOCKS[*]}" | sort -n )
do
echo "${BLOCKS[$TIME]}"
echo
done
同じ基本的なアイデア - 空の行に達するまで行を繰り返し、その時点で日付/時刻としてキー付きハッシュに保存します。すべての行が消費されると、ハッシュキーでソートされたすべてのチャンクが出力されます。