여러 줄에 여러 패턴을 배치하고 같은 줄에 인쇄

여러 줄에 여러 패턴을 배치하고 같은 줄에 인쇄

패턴 중 하나가 날짜와 시간을 포함하는 패턴인 다른 줄의 파일에 있는 정보를 찾는 방법을 찾으려고 합니다.

아래는 입력입니다

unwantedtext unwantedtext unwantedtext unwantedtext 8/1/2022 6:15 (1st required pattern using date and time format and the date and time can be changed)

unwantedtext unwantedtext unwantedtext unwantedtext 
unwantedtext unwantedtext INC-220721-00007628 (2nd required pattern)

또한 두 번째 파일에서도 두 번째 패턴 중 일부가 항상 세 번째 줄에 있는 것은 아니지만 날짜 및 시간 정보와는 확실히 다른 줄에 있습니다.

두 번째 패턴은 항상 INC로 시작하고 그 뒤에 연도, 월, 날짜 정보가 옵니다.

INC

항상 이 INC를 처음 3자리에 입력하세요.

INC-YYMMDD

INC 다음에 날짜와 시간이 옵니다.

INC-YYMMDD-00000000

YYMMDD 뒤에는 임의의 8자리 숫자가 옵니다.

-

하이픈은 항상 두 번째 패턴을 구분하는 역할을 합니다.

나는 다음과 같은 결과를 기대하고 있습니다

INC-220721-00007628,8/1/2022 6:15 

테스트에는 Windows CYGWYN을 사용하고 많은 양의 파일에는 CENTOS 7을 사용합니다.

모든 제안에 미리 감사드립니다.

답변1

값은 다음과 같다고 가정합니다.언제나쌍으로 grep찾을 수 있으며 paste다음과 결합할 수 있습니다.

$ grep -oP '\b\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{2}|INC-\d{6}-\d{8}\b' file | 
  paste -d "," - - 
8/1/2022 6:15,INC-220721-00007628

답변2

grep혼자서는 할 수 없습니다 . 아마도 sedPITA를 사용하여 이 작업을 수행할 수 있으며 패턴과 보유 공간에 대해 현재 가지고 있는 것보다 더 많은 지식이 필요할 것입니다(그리고 해당 지식은 다른 언어로 수행하기가 더 쉽기 때문에 일반적으로 배울 가치가 없습니다).

간단히 말해서, 당신은 사용해야합니다또는. 예를 들어:

$ perl -lne 'BEGIN { $, = "," };

             if (m=(\b\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{1,2}\b)=) {
               $dt = $1
             } elsif (m/(INC-\d+-\d+)/) {
               print $1, $dt;
               #$dt = ""; # uncomment to clear $dt before next input line
             }' input.txt 
INC-220721-00007628,8/1/2022 6:15

이 Perl 한 줄 스크립트는 Perl의 -l옵션을 사용하여 입력을 읽고 출력을 인쇄하는 동안(예: \nUnix 또는 \r\nWindows에서) 줄 끝을 자동으로 처리합니다. 이 옵션은 Perl이 다음 -n과 같이 작동하도록 합니다 sed -n. -e펄로 실행합니다.

먼저 이 스크립트는 출력 필드 구분 기호( $,)를 쉼표로 설정합니다. 이 변수는 다음에 기록됩니다.맨 퍼바르. BEGIN {...}각 입력 줄을 읽을 때마다 한 번이 아니라 스크립트가 시작될 때 한 번만 실행되도록 블록에서 이 작업을 수행합니다 .

그런데, Perl을 사용하도록 선택할 수 있습니다영어비밀스러운 단일 문자 변수 이름이 마음에 들지 않거나 기억할 수 없는 경우( use English;스크립트 내부 또는 -MEnglish한 줄의 코드) 이를 통해 긴 설명이 포함된 영어 별칭 및 awk와 유사한 해당 이름(해당되는 경우)에 액세스할 수 있습니다. 짧은 변수. 예를 들어, 또는 awk와 같은 명령을 use English사용할 수 있습니다 . 모두 동일한 의미를 가지며 동일한 변수를 참조합니다.$,$OUTPUT_FIELD_SEPARATOR$OFS

스크립트는 Perl의 정규식 일치 연산자를 사용하여 m원하는 패턴을 일치시키고 정규식의 괄호로 인해 캡처합니다. 바라보다맨 펄롭그리고 "를 검색해 보세요.m/패턴". 처음 사용할 때는 날짜 패턴에서 s를 이스케이프하지 않도록 정규식 구분 기호로 사용했습니다 m. 두 번째에는 더 친숙한 을 사용했습니다 .=//

매뉴얼 페이지도 참조하십시오.페레, 또한필수그리고페레튜트.

읽은 각 입력 줄에 대해 필요한 날짜 및 시간 패턴과 일치하려고 시도하고, 성공하면 캡처된 날짜 및 시간을 저장합니다(Perl의 하위 패턴 일치 변수에서 이는 제목 "부분"을 찾아 검색하는 것과 유사 $1합니다).\1sedman perlvar정규식 관련 변수")라는 변수에 $dt.

이전 일치가 실패하면 INC-\d+-\d+패턴 일치를 시도합니다. 성공하면 캡처된 패턴과 $dt변수가 인쇄됩니다.

다른 모든 입력은 무시됩니다.

아니면 awk를 사용하세요:

$ awk -v OFS=, '
  match($0,/\<[[:digit:]]{1,2}\/[[:digit:]]{1,2}\/[[:digit:]]{4} [[:digit:]]{1,2}:[[:digit:]]{1,2}\>/,a) {
    dt = a[0]; next
  };
  match($0,/INC-[[:digit:]]+-[[:digit:]]+/,a) {
    print a[0], dt
  }' input.txt 
INC-220721-00007628,8/1/2022 6:15

awk에는 awk 변수를 설정하는 편리한 -v옵션이 있으므로 OFS를 설정하는 데 블록이 필요하지 않습니다 BEGIN.

이 awk 한 줄짜리 내용은 Perl 버전을 거의 직접 번역한 것이지만 match()일치 및 캡처 테스트를 위해 awk의 기능을 사용합니다. 모든 일치 항목을 배열로 캡처합니다 a.

또한 [[:digit:]]perl에 해당하는 를 사용합니다. 많은 로케일에서 대신 \dusing을 사용할 수 있지만 둘 다 와 perl은 모든 로케일에서 작동합니다.[0-9][[:digit:]]\d

답변3

grep -Eo 'INC-[[:digit:]]{6}-[[:digit:]]+|[[:digit:]]{1,2}/[[:digit:]]{1,2}/[[:digit:]]{4} [[:digit:]]{1,2}:[[:digit:]]{1,2}' inputfile.txt |
 tr '\n' ',' | 
 sed 's/,$//'

노트:

  • grep:
    • -o: 일치하는 표현식만 가져오기
    • -E: 확장 RE 수락
      • |패턴은 파이프( ), 부울 연산자 "or" 로 구분됩니다 .

결과 :

8/1/2022
INC-220721-00007628

순서는 입력 파일과 동일합니다.

  • tr ...: \n개행 문자( )를 쉼표( ,) 로 변환합니다.

결과 :

8/1/2022 6:15,INC-220721-00007628,
  • sed ...: 명령에 의해 추가된 마지막 tr쉼표를 검색하여 바꾸기/제거합니다.

결과 :

8/1/2022 6:15,INC-220721-00007628

답변4

다음 을 포함한 pcregrep다중 라인 모드 :

$ pcregrep -M -o2 -o1 --om-separator=, '(?s) (\d+/\d+/\d+ \d+:\d+) .*?(INC-\d{6}-\d{8})' your-file
INC-220721-00007628,8/1/2022 6:15

관련 정보