Ketika saya ingin menggabungkan file log, saya sering menggunakan cat logA.log logB.log | sort. Selama baris log dimulai dengan beberapa string seperti stempel waktu dalam format umum, itu tidak masalah.

Tapi bisakah saya mengurutkan garis dan menjaga garis yang tidak mengikuti aturan tertentu yang direkatkan ke garis utama aslinya? Pikirkan saja file log di mana seseorang mencatat sesuatu dengan linebreak di dalamnya (tanpa saya sadari)!

(berta.log)
2021-10-01 00:00:10 Hey!
2021-10-01 00:00:11 How are you doing, Adam?

(caesar.log)
2021-10-01 00:00:00 Hey Berta
2021-10-01 00:00:20 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.
    at Conversation.parseStatement
    at Conversation.considerReplyToStatement
    at Conversation.doConversation
2021-10-01 00:00:40 I am not Adam, I am Caesar!

Kedua file log ini tentu saja akan menjadi tidak dapat digunakan jika digabungkan dengan cat berta.log caesar.log | sort.

Saya juga sangat tidak yakin apakah saya harus memposting pertanyaan ini ke StackOverflow atau Superuser atau bahkan ke Unix atau ServerFault...

Edit untuk kejelasan

Log yang digabungkan akan terlihat mis. seperti ini:

2021-10-01 00:00:00 Hey Berta
2021-10-01 00:00:10 Hey!
2021-10-01 00:00:11 How are you doing, Adam?
2021-10-01 00:00:20 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.
    at Conversation.parseStatement
    at Conversation.considerReplyToStatement
    at Conversation.doConversation
2021-10-01 00:00:40 I am not Adam, I am Caesar!
1
Bowi 1 Oktober 2021, 13:19

2 jawaban

Jawaban Terbaik

Masalah klasik pencampuran garis dan file.

Solusi: Letakkan baris log multiline Anda pada satu baris

  1. Skrip yang dapat dieksekusi: ./onelinelog.awk
#! /usr/bin/awk -f

# Timestamp line
/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] / {
    if (log_line != "") { print log_line }
    log_line = $0
    next
}
# Other line
{
    # Here, I use '§' for separate each original lines
    log_line = log_line "§" $0
}
# End of file
END {
    if (log_line != "") { print log_line }
}

Uji pada file caesar.log:

$ ./onelinelog.awk caesar.log 
2021-10-01 00:00:00 Hey Berta
2021-10-01 00:00:20 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.§    at Conversation.parseStatement§    at Conversation.considerReplyToStatement§    at Conversation.doConversation
2021-10-01 00:00:40 I am not Adam, I am Caesar!
  1. Menyortir:
cat <(./onelinelog.awk caesar.log) <(./onelinelog.awk berta.log) | sort

Atau

sort <(./onelinelog.awk caesar.log) <(./onelinelog.awk berta.log)

Keluaran:

2021-10-01 00:00:00 Hey Berta
2021-10-01 00:00:10 Hey!
2021-10-01 00:00:11 How are you doing, Adam?
2021-10-01 00:00:20 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.§    at Conversation.parseStatement§    at Conversation.considerReplyToStatement§    at Conversation.doConversation
2021-10-01 00:00:40 I am not Adam, I am Caesar!

Seru ?

Anda mungkin ingin memulihkan baris asli Anda...

Gunakan sed:

$ cat and/or sort ... | sed -e 's/§/\n/g'

Atau skrip awk lain yang dapat dieksekusi: ./tomultilinelog.awk

#! /usr/bin/awk -f
BEGIN {
    FS="§"
}
{
    for (i = 1; i <= NF; i += 1) { print $i }
}

Jadi jalankan:

$ cat <(./onelinelog.awk caesar.log) <(./onelinelog.awk berta.log) | sort | ./tomultilinelog.awk 
2021-10-01 00:00:00 Hey Berta
2021-10-01 00:00:10 Hey!
2021-10-01 00:00:11 How are you doing, Adam?
2021-10-01 00:00:20 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.
    at Conversation.parseStatement
    at Conversation.considerReplyToStatement
    at Conversation.doConversation
2021-10-01 00:00:40 I am not Adam, I am Caesar!

Tentu saja, Anda dapat mengadaptasi kode dan mengganti karakter '§' dengan token lain.

2
Arnaud Valmary 1 Oktober 2021, 11:12

Saya telah menemukan solusi awk lain sementara Arnaud Valmary mempostingnya.

Dalam upaya saya, saya hanya mengawali semua baris yang tidak dimulai dengan stempel waktu dengan stempel waktu terakhir (dan angka):

prefixAllLines.awk

#! /usr/bin/awk -f

BEGIN { 
    linePattern="^([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) (.*)" 
}
{ 
    if ($0~linePattern){
        number=0
        linePrefix=gensub(linePattern, "\\1", "g", $0)
        lineRest=gensub(linePattern, "\\2", "g", $0)
        printf linePrefix " " 
        printf ("%03d", number)
        printf " " lineRest "\n"
    } else {
        number+=1
        printf linePrefix " " 
        printf ("%03d", number)
        printf " " $0 "\n"
    }
}

Jadi, ./prefixAllLines.awk caesar.log membawa:

2021-10-01 00:00:00 000 Hey Berta
2021-10-01 00:00:20 000 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.
2021-10-01 00:00:20 001         at Conversation.parseStatement
2021-10-01 00:00:20 002         at Conversation.considerReplyToStatement
2021-10-01 00:00:20 003         at Conversation.doConversation
2021-10-01 00:00:40 000 I am not Adam, I am Caesar!

Dan cat <(./prefixAllLines.awk caesar.log) <(./prefixAllLines.awk berta.log) | sort:

2021-10-01 00:00:00 000 Hey Berta
2021-10-01 00:00:10 000 Hey!
2021-10-01 00:00:11 000 How are you doing, Adam?
2021-10-01 00:00:20 000 Error: SomebodyCalledMeWithTheWrongNameException: I am not Adam.
2021-10-01 00:00:20 001         at Conversation.parseStatement
2021-10-01 00:00:20 002         at Conversation.considerReplyToStatement
2021-10-01 00:00:20 003         at Conversation.doConversation
2021-10-01 00:00:40 000 I am not Adam, I am Caesar!

Tapi saya lebih menyukai pendekatan Arnaud Valmary. :-)

0
Bowi 1 Oktober 2021, 11:34