2009-06-09 3 views
0

웹 로그를 구문 분석하고 로그의 각 부분이 올바른지 확인하는 루비 프로그램을 작성하려고합니다. 로그의 요청 문자열에서 대소 문자를 처리하려고하면 시작 및 끝 부분 외에 추가로 큰 따옴표가 있습니다. 웹 로그를 정규 표현식으로 만들었습니다. 왜냐하면 각 부분에 대한 변수를 만드는 것이 더 쉽기 때문입니다. 여기에 지금까지 가지고 wut의 :웹 로그 요청 문자열에 추가 큰 따옴표 제거하기

isVal = true 
lines = lg.readlines 
logLine_regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}) - (\w*|-) \[(\d{2})\/(\w{3})\/(\d{4}):(\d{2}):(\d{2}):(\d{2})\s(-0400)\] (".*") (\d+) (\d+|-)$/ 

lines.each{ |line| 

    linePos = logLine_regex.match(line) 

    if linePos == nil 
     isVal = false 
    elsif linePos[0] != line.chomp 
     isVal = false 
    elsif !((0..255).include?(linePos[1].to_i)) 
     isVal = false 
    elsif !((0..255).include?(linePos[2].to_i)) 
     isVal = false 
    elsif !((0..255).include?(linePos[3].to_i)) 
     isVal = false 
    elsif !((0..255).include?(linePos[4].to_i)) 
     isVal = false 
    #linePos[5] = Username or hyphen 
    elsif !((1..31).include?(linePos[6].to_i)) 
     isVal = false 
    elsif !(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].include?(linePos[7])) 
     isVal = false 
    elsif !((0..9999).include?(linePos[8].to_i)) 
     isVal = false 
    elsif !((0..23).include?(linePos[9].to_i)) 
     isVal = false 
    elsif !((0..59).include?(linePos[10].to_i)) 
     isVal = false 
    elsif !((0..59).include?(linePos[11].to_i)) 
     isVal = false 
    #linePos[12] = -4000 
    #linePos[13] = request 
    elsif !((0..9999).include?(linePos[14].to_i)) 
     isVal = false 
    #linePos[15] = bytes 
    else 
     isVal = true 
    end 

} 

나는 그들이 추가하는 경우 따옴표는 백 슬래시를 앞에 탈출 수 있다는 것을 알고,하지만 난 어떻게 루비에서 코딩하는 생각이 없습니다. 도와주세요??

+0

몇 가지 예제 로그 라인을 게시하여 문제를 표시 할 수 있습니까? 또한이 형식을 가독성을 위해 고려해야 할 수도 있습니다. q1, q2, q3, q4, day, mon, year, hour, minute, second, foo = logLine_regex.match (line) – user60401

답변

1

단순한 토큰으로 정규 표현식을 정의하는 것이 간단합니다. 여기서는 문자열의 내용을 백 슬래시 - 따옴표 또는 따옴표가 아닌 문자가 아닌 0 개 이상의 인스턴스로 정의했습니다.

examples = [ 
    '"foo"', 
    '"foo\"bar\""', 
    'empty', 
    'one more "time"', 
    'the "last" man "standing"' 
] 

examples.each do |example| 
    puts "%s => %s" % [ example, example.match(/\"(?:\\"|[^"])*?\"/) ] 
end 

주어진 예제를 통해 어떻게 작동하는지 확인할 수 있습니다.

로그 파일 내용을 디코딩하는 전략에 대한 메모로서 길고 지루한 일련의 진술로 확인하는 것이 심각한 성능 저하의 원인이 될 수 있습니다. 특정 필드의 내용을 검증하는 다양한 방법을 광범위하게 벤치마킹 할 수 있습니다. 예를 들어, .to_i를 실행하는 것보다 해시에 0.255의 모든 유효한 숫자의 Fixnum 등가물을 저장 한 다음 낮은 값과 높은 값을 비교하는 것이 더 효율적일 수 있습니다.

0

첫째는,의 조각으로 당신의 정규식을 무너 뜨리는하자, 그래서 당신은 BYTE_RE는 그 정수 값이 255 인 문자열을 받아

BYTE_RE = /(?:[012]?\d)?\d/ 
IP_RE = /#{BYTE_RE}(?:\.#{BYTE_RE}){3}/ 
DAY_RE = /0?[1-9]|[12]\d|3[01]/ 
MONTH_RE = /Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/ 
YEAR_RE = /\d{4}/ 
DATE_RE = %r!#{DAY_RE}/#{MONTH_RE}/#{YEAR_RE}! 
HOUR_RE = /[01]?\d|2[0-3]/ 
MIN_RE = /[0-5]\d/ 
SEC_RE = MIN_RE 
TIME_RE = /#{HOUR_RE}:#{MIN_RE}:#{SEC_RE}\s-400/ 
DATETIME_RE = /#{DATE_RE}:#{TIME_RE}/ 
STRING_RE = /"(?:\\.|[^\\"])*"/ 

logLine_regex = /^#{IP_RE} - (?:\w*|-) \[#{DATETIME_RE}\] #{STRING_RE} \d{4} (?:\d+|-)$/ 
isVal = lg.readlines.all? { |line| line =~ logLine_regex } 

모든 사후 검증을 할 필요가 없습니다, 그래서 우리 그 후에 유효성 검사를하지 않아도됩니다. 여기에는 000이 포함되므로, 0으로 시작하지 않고 숫자로 제한하려면 /\d|[1-9]\d|[12]\d\d/으로 변경하십시오.

DAY_RE은 정수 값이 1-31 인 문자열 만 허용합니다. 앞의 0을 제거하려면 /[1-9]|[12]\d|3[01]/을 사용하십시오. 예제에서 연도의 유효성을 검사 할 필요는 없습니다. 정확히 4 자리이므로 0과 9999 사이에 있어야합니다. . 우리는 14 번 항목에 대해이를 검증하지 않으려 고합니다.

HOUR_RE은 정수 값이 0-23 인 문자열 만 허용합니다. 선행 0을 허용하지 않으면 /1?\d|2[0-3]/이됩니다. MIN_RESEC_RE 제한은 우리가 STRING_RE를 사용하여 문자열을 검증하기 위해, 그리고 0과

59 사이의 정수 값 것과 문자열을 받아 들였다. 나는 이것을 망가뜨릴 것이다.

  • " - 오픈 인용
  • (?:...) - 그룹에 대한 좋은 비 캡처 괄호.
    • \\. - 어떤 백 슬래시 문자 조합 - 문자열을 탈출 일치 \n, \a, \\, 또는 \"
    • | 같은 - 위의 패턴이나
    • [^\\"] 다음 중 - 백 슬래시 또는 doublequote를 제외한 모든 문자
  • * - 앞의 원자 중 0 개 이상
  • " - 닫기 인용

그래서이 오픈 doublequote 이스케이프 문자 또는 일반 문자 수, 그리고 가까운 견적을 일치합니다.

^를 시작하고 종료 $ 앵커가 알아서하기 때문에, 정규식에 의해 확인 양이 전체 라인이 있는지 확인 할 필요가 없습니다.

그래서 우리는 사실 이후 모든 유효성 검사를 제거했습니다. 모든 행이 주어진 정규 표현식 과 일치하는지 알고 싶기 때문에 Enumerable#all?을 사용할 수 있습니다.이 행은 모든 행이 주어진 정규 표현식 과 일치하는 경우에만 true를 반환합니다. 또한 부작용으로 false가 반환되면 일찍 종료되므로이 경우 조금 더 빨리 이 실행됩니다.

관련 문제