멀티라인 패턴/데이터 추출

멀티라인 패턴/데이터 추출

약 100,000개의 파일에 다음과 같은 헤더가 있습니다. 각 행을 개별적으로 추출하고 각 레코드를 Excel에 병합했기 때문에 시간이 부족했고 이제 데이터를 추출하는 편리한 방법을 찾고 있습니다.

X-RSMF-Generator: RSMF 생성기 예제 라이브러리

X-RSMF 버전:1.0.0

X-RSMF 이벤트 수:53

X-RSMF-시작 날짜:2022-09-20T04:33:11-04:00

X-RSMF 종료 날짜:2022-09-20T16:47:56-04:00

X-RSMF-그룹 ID:GRP000000118

X-RSMF 보조 그룹 ID:GRP000000118_D_20220920

X-RSMF 포함이 제거됨:잘못된

X-RSMF-응용 프로그램:네이티브 메시지

X-RSMF 참가자:1인칭 <5156242756> 2인칭, 2인칭

[이메일 보호됨]<21243210277> 4명*** <345278652345>

MIME 버전: 1.0

모든 파일에 모든 줄이 존재하는 것은 아니며 마지막 필드에는 여러 줄이 포함될 수 있습니다. MIME 버전: 1.0 - 사용할 수 있을 것 같습니다.MIME 버전: 1.0중지로. 또한 각 항목 행에 대한 데이터만 필요합니다. ":"(콜론 공백) 앞의 모든 내용은 필드 헤더이므로 무시할 수 있습니다.

나는 각 라인과 파이프를 AWK에 연결할 수 있다고 생각하면서 sed를 사용하기 시작했습니다. 각 기둥을 만드세요.

#!/bin/sh

shopt -s nullglob
FILES=/mnt/c/Temp/rsmf/*.rsmf

for f in $FILES

do
    #echo "Processing $f"
    sed -rn \
    -e '/^X-RSMF-BeginDate:/{
        s/X-RSMF-BeginDate: //
        s/T/ /
        s/-0[45]:00/ /
        s/X-RSMF-Application://
        h
        #p
        }' \
    -e '/^X-RSMF-EndDate:/{
        s/X-RSMF-EndDate: //
        s/T/ /
        s/-0[45]:00/ /
        H
        #p
        }' \
     -e '/^X-RSMF-GroupID:/{
        s/X-RSMF-GroupID: //
        H
        x
        s/\r\n//gp
        }' \
         $f
done

결과 -

2022-10-05 12:54:27 2022-10-05 12:54:27 GRP000000001
2022-10-05 11:48:18 2022-10-05 11:48:18 GRP000000002

이 문제를 논의하기 전에 이 특정 프로젝트에 대한 최상의 방법과 사례에 대한 조언을 구하고 싶습니다.

아이디어? ?

답변1

그리고:

awk -F': ' 'BEGIN{ORS=" "}$1=="MIME-Version"{exit}{print $2}END{print "\n"}' file    

답변2

다음은 다소 구식이고 무차별적인 접근 방식입니다. 아마도 더 좋은 방법이 있을 것입니다. (그러나 귀하의 데이터에 대해 더 많이 알아야 하며 왜 Excel을 언급했는지 알아야 합니다. 데이터가 원래 스프레드시트에 있는 경우 직접 읽는 데 사용됩니까? Excel 또는 데이터를 추출하는 Open/Libre Office와 같은 Perl 모듈에서 제공한 샘플 데이터로 작동합니다.

이는 원하는 수의 입력 파일을 처리할 수 있습니다.

공백 대신 TAB( \t또는 Ctrl-I 또는 )을 출력 필드 구분 기호로 사용하도록 작성되었습니다.^I필드 데이터에 공백이 포함될 수 있으므로.

#!/usr/bin/perl

while (<>) {
  chomp;
  s/^\s*|\s*$//g;  # strip any leading and trailing whitespace
  next if /^$/;    # ignore all blank lines

  # split input line into @F array
  # $F[0] will contain the field name and
  # $F[1] will contain the field data
  # The field separator is a quite-forgiving zero-or-more spaces followed by
  # a colon followed by one-or-more spaces. This should cope with most minor
  # variants caused by manual extraction from Excel. 
  my @F = split /\s*:\s+/;

  # print the data at end of each input record (file)
  if (/^MIME-Version/) {
    # add space-separated @participants array to end of @record array
    push @record, join(" ", @participants);

    # print @record array, tab-separated
    print join("\t", @record), "\n";

    # clear both arrays, ready for next input file
    @record=();
    @participants=();
    next;
  };

  # fix up the date format
  if (/^X-RSMF-(Begin|End)Date/) {
    $F[1] =~ s/T/ /;
    $F[1] =~ s/-0[45]:00$//;
  };

  if (/^X-RSMF-Participants/) {
    # participants need to be handled differently because this field can
    # be multi-line.  Store in a separate @participants array
    push @participants, $F[1];

  } elsif ($#F == 0) {
    # lines without a field name get added to @participants array
    push @participants, $_;

  } else {
    # all other fields get added to @record array
    push @record, $F[1];
  }
}

예를 들어 파일에 저장하고 rsmf2tab.pl실행 가능하게 만든 chmod +x rsmf2tab.pl다음 실행합니다.

./rsmf2tab.pl /mnt/c/Temp/rsmf/*.rsmf

또는 .rsmf 파일이 여러 하위 디렉터리에 있는 경우:

find /mnt/c/Temp/rsmf/ -name '*.rsmf' -exec /path/to/rsmf2tab.pl {} +

샘플 출력은 샘플 데이터(예: file1.rsmf 및 file2.rsmf)의 두 복사본을 입력으로 사용하며 파이프를 통해 cat -A탭을 다음과 같이 표시합니다 ^I.

$ ./rsmf2tab.pl *.rsmf | cat -A
RSMF Generator Sample Library^I1.0.0^I53^I2022-09-20 04:33:11^I2022-09-20 16:47:56^IGRP000000118^IGRP000000118_D_20220920^IFalse^INative Messages^IPerson One <5156242756> Person two, Person three [email protected] <21243210277> Person four <345278652345>$
RSMF Generator Sample Library^I1.0.0^I53^I2022-09-20 04:33:11^I2022-09-20 16:47:56^IGRP000000118^IGRP000000118_D_20220920^IFalse^INative Messages^IPerson One <5156242756> Person two, Person three [email protected] <21243210277> Person four <345278652345>$

그런데 당신은진짜FILE=/mnt/c/Temp/rsmf/*.rsmf나는 더 이상 당신의 후계자 가 되고 싶지 않습니다 for f in $FILES. 파일에 공백 문자가 포함되어 있으면 중단됩니다. 어쨌든, 이것은 필요하지 않습니다. 그냥 실행 for f in /mnt/c/Temp/rsmf/*.rsmf하거나 (실행 중인 항목에 따라) 루프를 사용하지 않고 실행 중인 명령에 모든 파일 이름 인수를 전달하기만 하면 됩니다.

관련 정보