삽질/개발,엔지니어링

ChatGPT로 로그에서 필요 항목을 추출하는 정규표현식 만들기

maengis 2023. 2. 27. 20:32

저번주에 퇴근하고 집에 오는 길에 문득 그런 생각이 들었다.

 

'내가 직접 이걸 쓸 게 아니라, 제공하는 서비스에서 사용자에게 요구하는 것들을 어느 정도 대신해줄 수 있게 프롬프트엔지니어링 된 프롬프트를 제공해주면 어떨까?'

 

집에 와서 이래저래 해봤는데 생각보다 원하는 수준의 답을 못 받아서, 주말에도 이래저래 해보곤 팀내에 공유를 했는데 다들 관심도 없고, 그냥 쓰는 거 가이드 페이지 만드는 게 더 초점이 맞춰져 있는 거 같아서 주말에 시간 쓴 것도 아깝고 해서 혼자 삽질한 거 정리나 좀 해봤다.

 

[23-Apr-2020 14:18:49] PHP Warning:  Invalid argument supplied for foreach() in /foo/bar/a.php on line 204
[23-Apr-2020 14:19:22] PHP Notice:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75
[23-Apr-2020 14:24:47] PHP Fatal Error:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7

PHP 오류 로그인데, 원래는 PHP Warning인데 다양한 상황에 대한 정규표현식을 받으려고 Notice와 Fatal Error로 수정 했다.

추출하려는 건

 

시간: 23-Apr-2020 14:18:49

오류 수준: PHP Warning

오류 내용: Invalid argument supplied for foreach() in /foo/bar/a.php on line 204

 

이렇게 세 개고, 각각 time, level, message라고 해서 추출을 하려고 했다.

ChatGPT에게는 로그에서 각 항목을 추출해달라고 해야 해서, 처음에는 그냥 내가 하는 것처럼 적었다.

 

질문

[23-Apr-2020 14:18:49] PHP Warning:  Invalid argument supplied for foreach() in /foo/bar/a.php on line 204
[23-Apr-2020 14:19:22] PHP Notice:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75
[23-Apr-2020 14:24:47] PHP Fatal Error:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7

위 세 줄에서 정규표현식으로 항목별 값을 추출하려고 한다.

23-Apr-2020 14:18:49 = time
PHP Warning = level
Invalid argument supplied for foreach() in /foo/bar/a.php on line 204 = message

23-Apr-2020 14:19:22 = time
PHP Notice = level
unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75 = message

23-Apr-2020 14:18:49 = time
PHP Fatal Error = level
unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7 = message

위처럼 추출 하려면 어떤 정규표현식을 써야할까?

답변

다음과 같은 정규 표현식을 사용하여 각 항목에서 값을 추출할 수 있습니다.

regex

/^(\[.*?\])\s*(\w+\s+\w+):\s*(.*)$/

이 정규 표현식은 다음과 같이 작동합니다:

    /^: 문자열의 시작
    (\[.*?\]): 대괄호 안의 모든 문자열을 일치시킴.
    \s*: 공백이 0개 이상 일치
    (\w+\s+\w+): 두 개의 단어와 공백이 일치
    :\s*: ":"과 공백이 일치
    (.*): 문자열의 나머지 부분을 일치
    $: 문자열의 끝

따라서, 다음과 같이 PHP에서 사용할 수 있습니다.

php

$log1 = "[23-Apr-2020 14:18:49] PHP Warning:  Invalid argument supplied for foreach() in /foo/bar/a.php on line 204";
$log2 = "[23-Apr-2020 14:19:22] PHP Notice:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75";
$log3 = "[23-Apr-2020 14:24:47] PHP Fatal Error:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7";
$regex = "/^(\[.*?\])\s*(\w+\s+\w+):\s*(.*)$/";

if (preg_match($regex, $log1, $matches)) {
  $time1 = $matches[1];
  $level1 = $matches[2];
  $message1 = $matches[3];

  // 추출한 값 사용
  echo $time1 . "\n";
  echo $level1 . "\n";
  echo $message1 . "\n";
}

if (preg_match($regex, $log2, $matches)) {
  $time2 = $matches[1];
  $level2 = $matches[2];
  $message2 = $matches[3];

  // 추출한 값 사용
  echo $time2 . "\n";
  echo $level2 . "\n";
  echo $message2 . "\n";
}

if (preg_match($regex, $log3, $matches)) {
  $time3 = $matches[1];
  $level3 = $matches[2];
  $message3 = $matches[3];

  // 추출한 값 사용
  echo $time3 . "\n";
  echo $level3 . "\n";
  echo $message3 . "\n";
}

이 코드는 각 로그 항목에서 시간, 레벨 및 메시지를 추출하여 $time, $level, $message 변수에 저장합니다. 해당 변수를 사용하여 추출한 값을 출력하거나 다른 목적으로 사용할 수 있습니다.

 

친절하게 PHP로 예제 코드까지 작성해줬는데, 막상 해보면 로그 한 줄은 처리가 안 된다.

[23-Apr-2020 14:18:49]
PHP Warning
Invalid argument supplied for foreach() in /foo/bar/a.php on line 204
[23-Apr-2020 14:19:22]
PHP Notice
unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75

이에 대한 것도 ChatGPT가 한 답변에 있는데,

(\w+\s+\w+): 두 개의 단어와 공백이 일치

바로 이부분이다. PHP Fatal Error는 가운데 공백이 있어서 두 개의 단어가 아니라 세 개의 단어이기 때문.

 

질문을 조금씩 바꾸면서 결국 어느 정도 원하는 답을 받긴 했는데, 질문 자체를 잘못하고 있다는 생각이 들었다.

그래서 질문을 간단하게 로그 + 질문 + 결과의 형태로 다시 물었다.

 

질문

[23-Apr-2020 14:18:49] PHP Warning:  Invalid argument supplied for foreach() in /foo/bar/a.php on line 204
[23-Apr-2020 14:19:22] PHP Notice:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75
[23-Apr-2020 14:24:47] PHP Fatal Error:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7

위 로그에서 아래 내용들을 추출하는 정규표현식을 알고 싶어.

"23-Apr-2020 14:18:49"
"PHP Warning"
"Invalid argument supplied for foreach() in /foo/bar/a.php on line 204"

"23-Apr-2020 14:19:22"
"PHP Notice"
"unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75"

"23-Apr-2020 14:18:49"
"PHP Fatal Error"
"unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7"

결과

다음은 주어진 로그에서 필요한 정보를 추출하기 위한 정규표현식입니다:

(\d{2}-\w{3}-\d{4} \d{2}:\d{2}:\d{2}).*?(PHP \w+).*?(.*)$

위의 정규표현식은 로그의 각 라인에서 다음과 같은 세 개의 정보를 추출합니다:

날짜와 시간 (23-Apr-2020 14:18:49)
로그 레벨 (PHP Warning, PHP Notice, PHP Fatal Error)
로그 메시지 (Invalid argument supplied for foreach() in /foo/bar/a.php on line 204, unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75, unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7)
위의 정규표현식을 사용하여 각 라인에서 필요한 정보를 추출할 수 있습니다. 예를 들어 Python에서는 다음과 같이 사용할 수 있습니다:

import re

log = "[23-Apr-2020 14:18:49] PHP Warning:  Invalid argument supplied for foreach() in /foo/bar/a.php on line 204\n[23-Apr-2020 14:19:22] PHP Notice:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75\n[23-Apr-2020 14:24:47] PHP Fatal Error:  unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7"
regex = r"(\d{2}-\w{3}-\d{4} \d{2}:\d{2}:\d{2}).*?(PHP \w+).*?(.*)$"
matches = re.findall(regex, log, re.MULTILINE)

for match in matches:
    print("Date and Time:", match[0])
    print("Log Level:", match[1])
    print("Log Message:", match[2])
    print()

이 코드는 다음 출력을 생성합니다:

Date and Time: 23-Apr-2020 14:18:49
Log Level: PHP Warning
Log Message: Invalid argument supplied for foreach() in /foo/bar/a.php on line 204

Ωate and Time: 23-Apr-2020 14:19:22
Log Level: PHP Notice
Log Message: unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 75

Date and Time: 23-Apr-2020 14:24:47
Log Level:PHP Fatal Error
Log Message: unlink(/foo/bar): No such file or directory in /foo/bar/a.php on line 7

 

원하는 답을 받긴 했는데, 기존에는 PHP 코드를 예제로 주더니 파이썬 코드로 줬다.

계속 이거저거 더 해보니 PHP 코드보다는 파이썬 코드로 답변을 할 때가 정답이거나 정답에 가까웠다.

 

영어로 물어보면 나을까 싶긴 했는데, 내 입장에서는 질문 내용이 그리 어렵지 않아서 크게 영향은 없었을 거 같다.

반응형