사이에 행 개수를 알 수 없는 행 찾기

사이에 행 개수를 알 수 없는 행 찾기

다음 출력이 포함된 텍스트 파일이 있습니다.

file_0108.json
2023-02-22T01:15:05.531+0000    connected to: mongodb://[**REDACTED**]@localhost
2023-02-22T01:15:08.531+0000    [######..................] db.coll  64.7MB/255MB (25.4%)
2023-02-22T01:15:11.531+0000    [############............] db.coll  128MB/255MB (50.3%)
2023-02-22T01:15:14.531+0000    [##################......] db.coll  196MB/255MB (76.9%)
2023-02-22T01:15:17.286+0000    [########################] db.coll  255MB/255MB (100.0%)
2023-02-22T01:15:17.286+0000    380757 document(s) imported successfully. 0 document(s) failed to import.

파일 번호(0000 - 1000의 블록 시작) 모든 파일을 성공적으로 가져온 것은 아닙니다. 파일 이름으로 시작하고 다음으로 끝나는 모든 텍스트 블록을 어떻게 찾을 수 있습니까?

xxxxx document(s) imported successfully. 0 document(s) failed to import

그럼 삭제하고 오류만 남겨두시겠어요?
각 청크는 파일 이름과 청크 끝 사이에 서로 다른 줄 수를 가질 수 있습니다.
일부 블록에는 오류가 있지만 오류가 다를 수 있으므로 오류 없이 블록을 삭제하는 것이 더 쉬울 것이라고 생각합니다.

오류 블록 예:

file_0293.json  
2023-02-22T01:52:15.303+0000    connected to: mongodb://[**REDACTED**]@localhost  
2023-02-22T01:52:16.836+0000    Failed: error processing document #46401: invalid character ',' after object key  
2023-02-22T01:52:16.836+0000    46000 document(s) imported successfully. 0 document(s) failed to import.

답변1

만약 있다면각 블록 내에 빈 줄이 없습니다.텍스트를 입력한 다음 sed각 줄 뒤에 빈 줄을 삽입한 imported successfully다음 파일을 "단락"(하나 이상의 빈 줄로 구분된 텍스트 블록)으로 처리할 수 있습니다. 예를 들어:

sed -e $'/imported successfully/a\\\n' filename |
  perl -00 -n -e 'print if /Failed:/'

for또한 귀하의 의견에서 bash 루프를 실행하여 입력 파일이 생성된다고 언급하셨습니다 echo <filename> && mongoimport. echo <filename> && mongoimport ; echo향후 실행 시 출력이 이미 단락으로 나누어지도록 실행으로 변경하는 것이 좋습니다 . sed더 이상 개행 문자를 삽입할 필요가 없으므로 다음을 실행할 수 있습니다.

perl -00 -n -e 'print if /Failed:/' filename

답변2

출력과 함께 다음 텍스트 파일을 사용해 보았습니다.

file_0108.json
2023-02-22T01:15:05.531+0000    connected to: mongodb://[**REDACTED**]@localhost
2023-02-22T01:15:08.531+0000    [######..................] db.coll  64.7MB/255MB (25.4%)
2023-02-22T01:15:11.531+0000    [############............] db.coll  128MB/255MB (50.3%)
2023-02-22T01:15:14.531+0000    [##################......] db.coll  196MB/255MB (76.9%)
2023-02-22T01:15:17.286+0000    [########################] db.coll  255MB/255MB (100.0%)
2023-02-22T01:15:17.286+0000    380757 document(s) imported successfully. 0 document(s) failed to import.
file_0293.json  
2023-02-22T01:52:15.303+0000    connected to: mongodb://[**REDACTED**]@localhost  
2023-02-22T01:52:16.836+0000    Failed: error processing document #46401: invalid character ',' after object key  
2023-02-22T01:52:16.836+0000    Failed: error processing document #46427: invalid character ',' after object key  
2023-02-22T01:52:16.836+0000    46000 document(s) imported successfully. 0 document(s) failed to import.

아래 명령줄은 터미널에 유용한 출력을 생성합니다.

$ grep -e 'file_.*\.json' -e 'Failed:' file.txt | sed 's/json/json:/'|grep -B1 'Failed:'
file_0293.json:  
2023-02-22T01:52:16.836+0000    Failed: error processing document #46401: invalid character ',' after object key  
2023-02-22T01:52:16.836+0000    Failed: error processing document #46427: invalid character ',' after object key  

원하는 경우 파일로 리디렉션할 수 있습니다. 예를 들어 출력이 stdout 및 error로 인쇄되도록 할 수 있습니다 ... > errors.txt 2>&1.

grep -e 'file_.*\.json' -e 'Failed:' file.txt | sed 's/json/json:/'|grep -B1 'Failed:' > errors.txt 2>&1

답변3

사용 awk:

awk -v startblock='^file_[0-9][0-9][0-9][0-9]\\.json$' \
    -v endblock='document\\(s\\) failed to import\\.$' '
    $0 ~ startblock {
        error=0
        s=""
    }
    {
        s=(s=="" ? "" : s ORS) $0
    }
    $0 ~ endblock && (error || $0 !~ " 0 " endblock) {
        print s
        next
    }
    tolower($0) ~ /failed|error|invalid/ {
        error=1
    }
' file

이렇게 하면 대소문자를 구분하지 않는 일치 항목 이나 failed블록 의 시작과 끝 사이 또는 블록 줄의 끝 부분에 0이 아닌 위치가 포함된 모든 블록이 인쇄됩니다 .errorinvalidn document(s) failed to import.n

답변4

요청한 작업을 수행하기 위해 awk를 사용하려면 다음을 수행하십시오.

awk '
    /^file_[0-9]+\.json$/ {
        printf "%s", rec
        rec = ""
    }
    { rec = rec $0 ORS }
    /document\(s) imported successfully. 0 document\(s) failed to import/ {
        rec = ""
    }
    END { printf "%s", rec }
' file

그러나 게시한 샘플 입력이 요구 사항과 일치하지 않습니다. 내 생각에 당신이 정말로 원하는 것은 (다시 awk를 사용하는 것입니다):

awk '
    /^file_[0-9]+\.json$/ {
        if ( !bad ) printf "%s", rec
        rec = bad = ""
    }
    /Failed:/ { bad = 1 }
    { rec = rec $0 ORS }
    END { if ( !bad ) printf "%s", rec }
' file

관련 정보