라인 클러스터로 파일을 검색한 다음 해당 라인을 삭제하는 방법은 무엇입니까?

라인 클러스터로 파일을 검색한 다음 해당 라인을 삭제하는 방법은 무엇입니까?

반복되는 특성 목록인 로그 파일이 있습니다. 예를 들어:

## This is the pattern of lines
time
urgency
icon_path
summary
body
appname

## Below is what the log file would actually look like
12:30
critical

test notification
notification
notify-send
11:00
low

earlier notification
notification
notify-send
10:46
normal

hello
world
dunstify

내 검색어와 일치하는 줄 블록/클러스터를 검색한 다음 bash에서 삭제하는 방법을 찾으려고 합니다. 위의 예에서 볼 수 있듯이 줄이 비어 있는 경우도 있고 채워지는 경우도 있습니다. 지금까지 내가 찾은 최고의 "솔루션"은 sed '/12:30/,+5 d'or 약간 더 나은 sed '/12:30/,/notify-send/d'. 이 두 가지 모두의 문제점은 첫 번째 항목이 타임스탬프의 모든 항목을 삭제하여 둘 이상의 로그 항목을 삭제한다는 것입니다. 다른 명령의 문제점은 동일한 시간과 appname을 가진 항목이 두 개 이상 있으면 일치하는 모든 항목이 삭제된다는 것입니다.

내가 일하려고 노력했지만 눈에 띄게 실패했던 것은 다음과 같은 일을 하는 것입니다 sed '/12:30\n^.*$\n^.*$\ntest notification\nnotification\nnotify-send/d' /tmp/notification_log. 두 번째와 세 번째 줄은 무엇이든 될 수 있습니다(각각 긴급 및 icon_path 줄). 이것이 제가 사용한 이유입니다 ^.*$(솔직히 말해서 이것이 적절한 정규식인지 확실하지 않습니다).

편집: 위의 실패한 명령을 사용하면 다음과 같은 결과가 나올 것으로 예상됩니다.

11:00
low

earlier notification
notification
notify-send
10:46
normal

hello
world
dunstify

해당 명령에는 다음이 입력되었습니다.

12:30
*anything*
*anything*
test notification
notification
notify-send

답변1

모든 클러스터가 M 줄 길이이고 M이 고정되어 있고 클러스터가 겹치지 않고 클러스터의 시작 부분을 검색할 필요가 없다면 실제로 그렇게 어렵지는 않습니다. 우리의 경우 M은 6입니다.

sed여러 줄을 일치시킬 수 있지만 일반적으로 한 번에 한 줄씩 처리하므로 패턴 공간에 추가 줄을 명시적으로 추가해야 합니다. 당신은 그것을 수행합니다 N:

sed 'N;N;N;N;N; /12:30\n.*\n.*\ntest notification\nnotification\nnotify-send/d'

^나머지는 앵커 가 없는 코드입니다 $. 앵커는 종종 각각 "줄의 시작" 및 "줄의 끝"과 연관됩니다. 하지만 sed실제로는 "… 문자열"입니다. 한 번에 한 줄씩 처리 하면 sed차이가 없습니다. 우리의 경우 앵커는 "… 문자열"이라는 것을 확실히 기억해야 합니다. 중간에 놓는 것은 의미가 없습니다. 결코 어떤 것과도 일치하지 않을 것입니다. sed애초에 그것들을 앵커로 해석하지 않고 문자 그대로 해석할 것 ^입니다 $.

문자열 중간에 "... of the line" 앵커가 필요하지 않습니다. 마지막 줄을 제외한 모든 줄은 개행 문자 바로 앞에서 끝납니다. 모든 줄은 개행 문자 바로 다음에 시작됩니다. 그러니 충분히 일치합니다 \n.

.*아마도 앵커를 사용하여 (탐욕스럽고 개행 문자와 일치할 수 있음) 둘 이상의 행과 일치하지 않는지 확인하려고 시도했을 수도 있습니다 . "… 라인의" 앵커 역할을 한다고 ^해도 여전히 욕심이 많을 것입니다. 이것을 고려하십시오: 패턴 공간은 마지막 라인* 뒤에 개행 문자를 포함하지 않습니다. 우리의 경우에는 패턴 공간에 최대 6개의 라인이 있다는 것을 알고 있습니다. 정확히 5번 사용했습니다 . 이는 정규식의 각 조각이 클러스터의 특정 줄에만 일치할 수 있음을 보장합니다.$.*sed\n

스틸 앵커가 도움이 될 수 있습니다. 위 명령은 로 끝나는 클러스터를 삭제할 수 있습니다 notify-send-whatever. $이를 방지하는 올바른 방법입니다. 12:30일치하는 시간 외에는 시간이 없습니다 12:30. 하지만 의 경우에는 다르 2:30므로 일반적으로 ^유용할 수도 있습니다. 향상된 명령:

sed 'N;N;N;N;N; /^12:30\n.*\n.*\ntest notification\nnotification\nnotify-send$/d'

* 이는 패턴 공간 끝에 개행 문자가 절대 있을 수 없다는 의미는 아닙니다. 끝에 있는 개행 문자는 해당 문자 바로 뒤에 행이 있음을 나타냅니다. 마지막 줄이고 비어 있습니다. 그리고 그 뒤에는 줄바꿈 문자가 없으므로 "마지막 줄 뒤에는 줄바꿈 문자가 없습니다"가 나타납니다.

관련 정보