패턴 중 하나가 날짜와 시간을 포함하는 패턴인 다른 줄의 파일에 있는 정보를 찾는 방법을 찾으려고 합니다.
아래는 입력입니다
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
혼자서는 할 수 없습니다 . 아마도 sed
PITA를 사용하여 이 작업을 수행할 수 있으며 패턴과 보유 공간에 대해 현재 가지고 있는 것보다 더 많은 지식이 필요할 것입니다(그리고 해당 지식은 다른 언어로 수행하기가 더 쉽기 때문에 일반적으로 배울 가치가 없습니다).
간단히 말해서, 당신은 사용해야합니다앗또는진주. 예를 들어:
$ 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
옵션을 사용하여 입력을 읽고 출력을 인쇄하는 동안(예: \n
Unix 또는 \r\n
Windows에서) 줄 끝을 자동으로 처리합니다. 이 옵션은 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
합니다).\1
sed
man 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에 해당하는 를 사용합니다. 많은 로케일에서 대신 \d
using을 사용할 수 있지만 둘 다 와 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