저는 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
변환되는 것을 볼 수 있습니다. \2
1인당 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
다음 명령을 사용하여 원하는 출력을 얻을 수 있습니다pcregrep
Linux의 명령. 그것은 확장된다-o
옵션을 사용하면 선택한 캡처 그룹을 출력할 수 있습니다. 두 번째 세트를 원하므로 다음을 사용할 수 있습니다. -onumber
-o2
:
$ pcregrep -o2 '(\d{5})[-.]?\s*?(\d{6})' input
567890
222111
543210