텍스트 줄에서 숫자를 찾고 싶습니다.
cat log.txt | grep "License term"
01/01/2024:00:30 License term is 123 days.
나는 이것에서 "마이너스"를 분리하고 싶습니다. 키워드 일치 전후에 단어를 에코하는 방법이 있습니까? ""is" 다음에 문자열을 출력합니다" 또는 ""days" 전에 문자열을 출력합니다"처럼요?
아마 똑같을 것 같지만, 앞으로는 바뀔 수도 있습니다. (로그 항목에 대한 서식이나 기타 텍스트가 추가됩니다)
답변1
다음 명령은 정규식과 일치하는 모든 줄 , 즉 하위 문자열이 포함된 모든 줄 , 선택적인 양의 정수, 줄 끝에 하위 문자열이 뒤따르는 모든 sed
줄을 찾습니다 . 이러한 라인이 발견되면 전체 라인을 정수로 대체하고 수정된 라인을 출력하여 요청한 번호를 효과적으로 추출합니다.log.txt
.*License term is \([0-9]*\) days\.$
License term is
days.
sed -n 's/.*License term is \([0-9]*\) days\.$/\1/p' log.txt
또 다른 방법은 을 사용하는 것입니다 awk
. 다음은 문자열이 포함된 줄만 일치시킨 License term
다음 해당 줄에서 두 번째 공백으로 구분된 단어를 출력하는 약간 다른 접근 방식입니다.
awk '/License term/ { print $(NF-1) }' log.txt
분명히 문자열이 포함된 줄에서 공백으로 구분된 다섯 번째 필드를 제거하기 위해 와 grep
결합 할 수도 있습니다 .cut
License term
grep -F 'License term' log.txt | cut -d ' ' -f 5
여기서는 정규식 대신 문자열을 사용하여 검색하고 있음을 나타내기 위해 grep
해당 옵션을 사용하고 있습니다.-F
답변2
GNU에서는 및 옵션을 grep
사용할 수 있습니다 . 이는 각각 "줄에서 일치하는 부분만 인쇄" 및 "Perl 호환 정규 표현식 사용"을 의미합니다. PCRE의 경우 "지금까지 일치하는 항목을 모두 삭제합니다"라는 의미로 이를 사용할 수 있습니다 . 이 모든 것을 결합하면 다음과 같은 결과를 얻을 수 있습니다.-o
-P
\K
$ grep -oP 'License term is \K\d+' log.txt
123
물론 이것이 일관되게 작동할지 여부는 그 안에 무엇이 있는지에 따라 다르지만 log.txt
귀하의 예에서는 작동합니다.
답변3
pcre2grep
(또는 이전 버전 ) 과 함께 pcregrep
:
pcre2grep -xo1 '\d\d/\d\d/\d\d\d\d:\d\d:\d\d License term is (\d+) days\.' < log.txt
행은 보수적으로 일치하여 실제로 패턴과 일치하는 행만 선택하고 x
거기에서 첫 번째o
캡처링 그룹 과 일치하는 숫자가 출력됩니다.1
p
또는 Perl( in pcre2grep
) 과 동일합니다 .
perl -lne '
print $1 if m{^\d\d/\d\d/\d\d\d\d:\d\d:\d\d License term is (\d+) days\.$}
' < log.txt
답변4
사용행복하다(이전 Perl_6)
~$ raku -ne '.put if s/ .* "License term is " (<[0..9]>*) " days." $/$0/;' log.txt
#OR:
~$ raku -ne '.put if s/ .* License \s term \s is \s (<[0..9]>*) \s days \. $/$0/;' log.txt
#OR:
~$ raku -ne '.put if s/ .* License <.ws> term <.ws> is <.ws> (<[0..9]>*) <.ws> days \. $/$0/;' log.txt
또는:
~$ raku -ne 'if /License \s term/ { put .words[4] };' log.txt
#OR:
~$ raku -ne 'put .words[4] if /License \s term/;' log.txt
또는:
~$ raku -e '$0.put for lines.match(/ "License term is " ( \d+ ) /);' log.txt
#OR:
~$ raku -e '.put for lines.match(/ "License term is " ( \d+ ) /);' log.txt
Raku로 작성된 답변은 이미 게시된 우수한 답변과 여러 면에서 유사합니다 sed
. awk
처음 두 답변 세트는 -ne
자동 인쇄되지 않는 한 줄씩 플래그를 사용합니다. 첫 번째 그룹에서는 s///
이 양식을 사용하십시오 . 두 번째 그룹에서는 words
공백을 분할하는 데 Raku의 루틴이 사용됩니다. 마지막 답변 세트에서 Raku에는 lines
하위 키를 찾거나 반환하는 루틴이 있습니다 match
.
입력 예:
#dummy_line followed by blank line
01/01/2024:00:30 License term is 123 days.
#dummy_line
예제 출력:
123
Raku 정규식 엔진을 사용하면 캡처 태그와 미리보기/뒤돌아보기도 사용할 수 있습니다. 자세한 내용은 아래 첫 번째 링크를 참조하세요. 또한 <[0..9]>
ASCII 숫자 또는 \d
ASCII + 유니코드 숫자를 캡처하도록 선택할 수 있습니다 .