다음 내용을 포함하는 "test.log" 파일이 제공됩니다.
line1 Patient 123 45566
line2 Patient 432
line3 Patient 234 456
line4 Patient 321
line5
line 2
다음 패턴을 선택 하고 사용 하려고 합니다 line 4
.
grep "Patient\s\d+\s" test.log
# but this works testing at https://rubular.com/
작동하지 않으며 다음도 수행되지 않습니다.
grep "Patient\s\d+\n" test.log
# but this works testing at https://regexr.com/47qd5
내가 뭘 잘못했나요?
답변1
1. 명명된 클래스 또는 PCRE를 사용하세요.
GNU는 grep
기본적으로 기본 정규식(BRE)을 사용하지만 확장 정규식(ERE) 및 Perl 호환 정규식(PCRE)도 사용할 수 있습니다.
BRE와 ERE는 모두 지원되거나 \s
지원되지 않지만 \d
비슷한 기능을 가지고 있습니다. 에서 man grep
:
마지막으로 아래와 같이 특정 명명된 문자 클래스가 대괄호 표현식 내에 미리 정의되어 있습니다. 해당 이름은 설명이 필요하지 않습니다. 즉,
[:alnum:]
,[:alpha:]
,[:cntrl:]
,[:digit:]
,[:graph:]
,[:lower:]
,[:print:]
,[:punct:]
,[:space:]
및[:upper:]
입니다[:xdigit:]
. 예를 들어[[:alnum:]]
현재 로케일의 숫자와 문자를 나타내는 문자 클래스입니다. C 로캘 및 ASCII 문자 집합 인코딩에서 이는 와 동일합니다[0-9A-Za-z]
. (이러한 클래스 이름의 대괄호는 기호 이름의 일부이며 대괄호 표현식을 구분하는 대괄호와 함께 포함되어야 합니다.) 대부분의 메타 문자는 해당 문자를 잃습니다. 대괄호 표현식 내의 특별한 의미. 텍스트를 포함하려면]
목록의 첫 번째에 넣으세요. 마찬가지로 텍스트를 포함하려면^
시작 부분을 제외한 아무 곳에나 배치하세요. 마지막으로 텍스트를-
마지막에 넣으세요.
예:
$ grep -E '^[[:digit:]]+$' << 'EOF'
> foo
> 123
> bar
> EOF
123
\s
다음 을 지원하는 PCRE를 사용할 수도 있습니다 \d
.
$ grep -P '^\d+$' << 'EOF'
> foo
> 123
> bar
> EOF
123
2. \n
작동하지 않습니다
유닉스에서는 각각 \n
이 로 구분됩니다.철사. grep
인쇄철사주어진 패턴과 일치합니다. 이 경우 일치 \n
자체는 의미가 없습니다.
$
다음을 사용하여 줄 끝을 일치시킬 수 있습니다 .
$ grep -E 'foo bar$' << 'EOF'
> foo
> foo bar
> foo bar baz
> EOF
foo bar
또는 -z
/ --null-data
옵션을 전달하여 "여러 줄" 모드를 활성화합니다(원하는 것과 정확하게 일치하려면 몇 가지 추가 해결 방법이 필요합니다).
$ grep -Poz '(?<=\n)?foo bar\n' << 'EOF'
> foo
> foo bar
> foo bar baz
> EOF
foo bar
3. 첫 번째 예는 귀하의 생각과 맞지 않습니다.
마지막 것은 and 대신에 and 와 \s
일치합니다 :line 1
line 3
line 2
line 4
$ grep -P 'Patient\s\d+\s' << 'EOF'
> line1 Patient 123 45566
> line2 Patient 432
> line3 Patient 234 456
> line4 Patient 321
> line5
> EOF
line1 Patient 123 45566
line3 Patient 234 456
답변2
-P
Perl 정규식에 대해 GNU grep과 함께 스위치를 사용하면 구문이 원하는 대로 작동합니다.
$ grep -V | head -n1
grep (GNU grep) 2.25
$ grep --help | grep "\-P"
-P, --perl-regexp PATTERN is a Perl regular expression
또한보십시오이 답변더 많은 정보를 알고 싶습니다.
답변3
다른 사람들이 이미 지적했듯이 모든 정규 표현식이 동일한 표기법을 사용하는 것은 아닙니다. 기본 grep
구현이 GNU가 아닌 시스템을 사용하고 있다면 grep
POSIX 정규 표현식이 있고 Perl과 유사한 패턴(예: )을 사용하지 않는 것입니다 \s
.
grep
(0개 이상의 정수가 아닌) 단일 양의 정수로 끝나는 줄을 원하는 것 같습니다 . 데이터를 살펴보면 공백으로 구분된 3개의 필드만 포함하는 모든 행을 추출하려는 또 다른 방법입니다.
그것은 간단합니다 awk
:
$ awk 'NF == 3' test.log
line2 Patient 432
line4 Patient 321
NF
는 현재 레코드(행)의 필드(열) 수이며 조건 행은 하나만 있습니다. 기본 작업은 조건을 충족하는 모든 행을 인쇄하는 것입니다.
grep
, 및 보다 완전한 패턴을 사용하여 우리가 기대하는 것을 정확하게 지정하십시오.
$ grep -Ex '[[:alnum:]]+ [[:alpha:]]+ [[:digit:]]+' test.log
line2 Patient 432
line4 Patient 321
-E
확장 정규식을 활성화하고 (확장 +
수정자를 사용하므로) 전체 줄이 일치하도록 -x
합니다 .grep
[[:alnum:]]+
로케일에 따라 문자 및 숫자와 일치하고, [[:alpha:]]+
및 는 [[:digit:]]+
각각 문자 및 숫자 문자열과 일치합니다.
ASCII 범위를 사용하여 동일한 내용을 작성하는 또 다른 방법(로케일 무시):
grep -Ex '[A-Za-z0-9]+ [A-Za-z]+ [0-9]+' test.log
답변4
오래된 MacOS에서 실행 중이던 grep 버전은 grep (BSD grep) 2.5.1-FreeBSD
지원되지 않았기 -P
때문에 3.3을 설치 brew install grep --with-default-names
하고 작동시킬 수 있었습니다.
grep -P 'Patient\s\d+$' test.log