이 비캡처 그룹에 grep이 도움이 될 수 있습니까?

이 비캡처 그룹에 grep이 도움이 될 수 있습니까?

저는 GNU/Linux와 정규 표현식을 처음 접했습니다. 최근에는 정규식을 익히려고 노력하고 있습니다. 지금까지는 꽤 탄탄한 기본 이해를 갖고 있다고 생각합니다. 지금 PCRE를 파고 있어요.

이것은 제가 사용하고 있는 연습 텍스트 파일입니다:

01234 567890

01111-222111

09876.543210

다음을 수행하여 성공적으로 숫자를 일치시킬 수 있습니다.

(\d{5})[-.]?\s*?(\d{6})

이제 처음 5자리는 생략하고 마지막 6자리만 일치하도록 비캡처 그룹을 만들고 싶습니다. 그래서 저는 (?:)캡처하지 않는 그룹을 대표하고 캡처하고 싶지 않은 것을 입력한 것 같아요 . 그렇죠? 그래서 그건

(?:\d{5})[-.]?\s*?(\d{6})

터미널에서 PCRE를 사용하여 grep -Po출력을 표시하면서 이 작업을 수행했는데 마치 비캡처 그룹이 적용되지 않은 것처럼 여전히 정확히 일치하는 결과를 얻었습니다.

어떤 지침이 있습니까?

답변1

-o또는 옵션을 사용할 때 캡처는 grep이 일치의 일부로 간주하는 항목에 영향을 미치지 않습니다 --only-matching. 모든 비캡처는 그룹이 사용 가능한 역참조 중 하나로 계산되거나 교체가 선택 사항인 컨텍스트에서 교체되지 않음을 의미합니다.

예를 들어:

$ printf 'aba\nabb\nabc\n' | grep -Po '(a)(b)'
ab
ab
ab
$ printf 'aba\nabb\nabc\n' | grep -Po '(a)(b)\1'
aba
$ printf 'aba\nabb\nabc\n' | grep -Po '(?:a)(b)\1'
abb

아마도 이 경우에 당신이 찾고 있는 것은길이가 0인 줄 뒤 주장:

printf 'aba\nabb\nabc\n' | grep -Po '(?<=a)b'
b
b
b

아니면 \K"왼쪽을 유지하라"는 생각

$ printf 'aba\nabb\nabc\n' | grep -Po 'a\Kb'
b
b
b

(후자는 가변 길이 일치를 허용하므로 약간 더 유연합니다).

예를 들어

$ grep -Po '\d{5}[-.]?\s*\K\d{6}' file
567890
222111
543210

답변2

사용중인 정규식은 일치하기에는 너무 복잡해 보입니다.하나중간 문자는 -, a .또는 공백일 수 있습니다. 왜 필요한가요 [-.]?\s*?? 다음과 같습니다: a -또는 a .(선택 사항(`?))와 일치하고 그 뒤에 공백이 옵니다(음, 실제로는 (man pcrepattern에서)):이제 기본 \s 문자는 HT(9), LF(10), VT(11), FF(12), CR(13) 및 공백(32)입니다.). 글쎄요, 실제로 게으른 모드에는 몇 개의 공백(*?)이 있습니다.

[ .-]제 생각에는 한 문자, 공백, 점 또는 대시 만 있으면 됩니다 . 이 정규식은 다음과 같습니다.

(\d{5})[-. ](\d{6})

이를 시험해 볼 수 있는 가장 좋은 곳(정규식을 배울 수 있는 유일한 실제 방법)은 regex101.com에 가서 시험해 보는 것입니다. 여기이 게시물의 예제를 만들었습니다.자세한 정보(PCRE에서는 예).

당신이 질문한 대체 항목에서 저는 다음과 같은 대체 항목을 배치한 것을 볼 수 있습니다.

(one:\1) (two:\2) (three:3)

각 줄에서 주변 텍스트 대신 전체 일치 항목(정규식의 처음부터 끝까지)이 해당 문자열로 대체되고 합계가 캡처된 값으로 \1변환되는 것을 볼 수 있습니다. \21인당 1인분 (...).

(...)첫 번째 비 캡처를 만들고 싶다면 다음을 수행하십시오.하나그룹을 캡처하는 경우 대체 항목을 다음으로 변경해야 합니다.

(one:1) (two:\1) (three:3)

단 하나 \1. 그렇지 않으면 교체가 실패합니다.

전체 줄을 바꾸려면 처음부터 끝까지 전체 줄과 일치하도록 만드세요.

^.*(?:\d{5})[-. ](\d{6}).*$

\1마지막 숫자 세트만 인쇄하려면 교체를 수행하세요 .

이제 grep에 대해 알아보겠습니다. Grep을 대체할 수는 없습니다. "다소" 도움이 되지만 그에 상응하는 것은 아닙니다 \K.

grep -Po '^.*\d{5}[-. ]\K\d{6}' file

중요한 아이디어는 -o정규식이 일치하는 모든 것, 예, 각 일치하는 대괄호보다는 전체 정규식을 제공하는 것을 목표로 하는 것입니다.

실제 대체(또는 대체( s///))를 사용하려면 다음이 필요합니다 sed(그러나 PCRE 대신 BRE를 사용함).

$ sed 's/^.*\([0-9]\{5\}\)[-. ]\([0-9]\{6\}\).*$/ \2 \1 /' file
 567890 01234 
 222111 01111 
 543210 09876

이는 실제로 대체이므로 순서 변경(또는 중복)이 허용됩니다.

답변3

grep마지막 6자가 숫자인 줄 블록을 출력 하려면 다음과 같이 말하십시오.

grep -Po "\d{6}$" file

구분 기호를 결정하려면 다음 모양을 추가하십시오.

grep -Po "(?<=[-. ])\d{6}$" file

또는 자릿수가 불확실한 경우

grep -Po "\d+$" file

두 경우 모두 줄 끝에 고정하고 다시 연결하면 됩니다.

나는 가장 좋은 계획은 일반적으로 처리할 필요가 없는 부분은 처리하지 않는 것이라고 생각합니다.모든배움을 위해 어려운 일을 하는 것의 미덕...그냥 계속하세요 ;D).

답변4

다음 명령을 사용하여 원하는 출력을 얻을 수 있습니다pcregrepLinux의 명령. 그것은 확장된다-o옵션을 사용하면 선택한 캡처 그룹을 출력할 수 있습니다. 두 번째 세트를 원하므로 다음을 사용할 수 있습니다. -onumber-o2:

$ pcregrep -o2 '(\d{5})[-.]?\s*?(\d{6})' input
567890
222111
543210

관련 정보