큰 텍스트 파일에서 grep / sed를 사용하여 날짜 범위에서 텍스트를 얻는 방법은 무엇입니까?


9

큰 파일 텍스트 (약 3GB)가 있습니다-로그 파일입니다. 이 파일에서 7 월 13 일부터 7 월 19 일까지의 날짜 범위에 해당하는 텍스트 줄을 얻고 싶습니다. 내 로그 형식은 다음과 같습니다

2016-07-12 < ?xml version>
2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>
2016-07-20 < ?xml version>
sample text sample text
sample text sample text
sample text sample text
2016-07-20 < ?xml version>
sample text sample text
2016-07-20 < ?xml version>

따라서 grep/ sed다음과 같이 출력되어야합니다 :

2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>

어떻게 구할 수 있습니까?


2
당신은 6 월 을 의미 합니까? 샘플 로그 파일의 모든 날짜는 7 월 이며 원하는 출력 샘플은 후자를 의미합니다.
David Foerster

답변:


13

함께 grep하면 행의 수를 알고있는 경우에 당신은 당신이 상황에 맞는 옵션을 사용할 수 있습니다 원하는 -A패턴 후 라인을 인쇄

grep -A 3 2016-07-13 file

2013-07-13 라인과 다음 3 라인을 제공합니다.

sed이 같은 구분하기 위해 날짜를 사용할 수 있습니다

sed -n '/2016-07-13/,/2016-07-19/p' file

2016-07-13의 첫 번째 줄부터 2016-07-19의 첫 번째 줄까지 모든 줄을 인쇄합니다. 그러나 2016-07-19에는 한 줄만 있다고 가정합니다 (다음 줄은 인쇄하지 않음). 여러 줄이있는 경우 대신 다음 날짜를 사용 d하여 출력을 삭제하십시오.

sed -n '/2016-07-13/,/2016-07-20/{/2016-07-20/d; p}' file

11

이 간단한 그렙 하나의 라이너로 충분합니다.

grep -E ^2016-07-1[3-9] filename

여기에서 잘 작동하며 sed가 필요하지 않습니다 :)

참고 문헌 :


1
언제나처럼 당신은 은혜를 가져옵니다 :)
Zanna

(y) ... ^작동 하려면 제거 해야했습니다. 맥 사용하기.
Anum Sheraz

4

awk 해결책:

$ awk '/^2016-07-13.*/,/2016-07-19.*/'  input.txt                                   
2016-07-13 < ?xml version> 
2016-07-18 < ?xml version> 
2016-07-18 < ?xml version> 
2016-07-19 < ?xml version> 

기본적으로 하나에서 모든 행을 인쇄 그와 시작 2016-07-13과 함께 시작되는 하나2016-07-19


4

다른 모든 현재 답변은 로그 파일 항목이 시간순으로 정렬된다는 사실 또는 날짜 범위를 정규식과 쉽게 일치시킬 수 있다는 사실에 의존합니다. 보다 일반적인 솔루션을 원한다면 프로그래밍을 더해야합니다.

이 GNU AWK 스크립트를 소개합니다 :

#!/usr/bin/gawk -f
BEGIN {
    starttime = mktime(starttime)
    endtime = mktime(endtime)
}

func in_range(n, start, end) {
    return start <= n && n < end
}

match($0, /^([0-9]{4})-([0-9]{2})-([0-9]{2})\s/, m) &&
    in_range(mktime(m[1] " " m[2] " " m[3] " 00 00 00"), starttime, endtime)

당신은 변수를 통해 시작 시간과 종료 시간을 제공 starttime하고 endtime형식으로 mktime이해한다 ( YYYY MM DD hh dd ss). 따라서 awk위의 Awk 스크립트가 filter-log-dates.awk현재 작업 디렉토리 의 실행 파일 에 있고 로그 파일이 mylog.txt다음 과 같다고 가정하면 명령을 다음과 같이 실행합니다 .

./filter-log-dates.awk -v starttime='2016 07 13 00 00 00' -v endtime='2016 07 20 00 00 00' mylog.txt

종료 시간은 배타적입니다 . 즉, 유효한 로그 레코드 에는 종료 시간 전에 타임 스탬프가 있어야합니다 .

타임 스탬프 형식이 다른 경우 match함수에 전달 된 정규식을 해당 형식에 맞게 조정할 수 있습니다 .


3

단계적으로 수행 할 수 있습니다. 시작 패턴과 일치하는 첫 번째 줄의 번호를 찾으십시오. 끝 패턴과 일치하는 마지막 줄의 번호를 찾으십시오. 그런 다음이 두 줄 사이에서 테스트를 추출하십시오. 이것은 다음과 같이 수행 할 수 있습니다.

grep -n 2016-07-13 bigtextfile | head -1
grep -n 2016-07-19 bigtestfile | tail -1
# Say the first number is 1234 and the second 5678, then use...
awk 'NR>=1234 && NR<=5678' bigtestfile > rangeoftext

이 작업은 모두 awk명령으로 수행 할 수 있지만 단계를 수행하기가 더 쉬울 수 있습니다. awk 내에서 NR 변수는 현재 행 번호이며 패턴 (NR> = 1234 && NR <= 5678) 다음에 조치가 지정되지 않았으므로 기본 조치는 해당 범위의 행을 인쇄하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.