정규식을 사용하여 grep -E
특정 순서가 아닌 모든 문자 집합을 포함하는 단어를 찾아야 합니다. 예를 들어, 모든 모음(aeiou)을 포함하지만 모음이 단어에서 어떤 순서로든 나타날 수 있는 단어입니다.
답변1
aeiou
"모든 것을 어떤 순서로 포함한다 " 는 규칙은 grep -E
적당한 크기의 POSIX 확장 정규식( )으로는 표현할 수 없습니다.
다음은 대안으로 사용되는 aeiou의 전체 120개 순열 목록입니다.
a.*e.*i.*o.*u|a.*e.*i.*u.*o|a.*e.*o.*i.*u|a.*e.*o.*u.*i|a.*e.*u.*i.*o|a.*e.*u.*o.*i|a.*i.*e.*o.*u|a.*i.*e.*u.*o|a.*i.*o.*e.*u|a.*i.*o.*u.*e|a.*i.*u.*e.*o|a.*i.*u.*o.*e|a.*o.*e.*i.*u|a.*o.*e.*u.*i|a.*o.*i.*e.*u|a.*o.*i.*u.*e|a.*o.*u.*e.*i|a.*o.*u.*i.*e|a.*u.*e.*i.*o|a.*u.*e.*o.*i|a.*u.*i.*e.*o|a.*u.*i.*o.*e|a.*u.*o.*e.*i|a.*u.*o.*i.*e|e.*a.*i.*o.*u|e.*a.*i.*u.*o|e.*a.*o.*i.*u|e.*a.*o.*u.*i|e.*a.*u.*i.*o|e.*a.*u.*o.*i|e.*i.*a.*o.*u|e.*i.*a.*u.*o|e.*i.*o.*a.*u|e.*i.*o.*u.*a|e.*i.*u.*a.*o|e.*i.*u.*o.*a|e.*o.*a.*i.*u|e.*o.*a.*u.*i|e.*o.*i.*a.*u|e.*o.*i.*u.*a|e.*o.*u.*a.*i|e.*o.*u.*i.*a|e.*u.*a.*i.*o|e.*u.*a.*o.*i|e.*u.*i.*a.*o|e.*u.*i.*o.*a|e.*u.*o.*a.*i|e.*u.*o.*i.*a|i.*a.*e.*o.*u|i.*a.*e.*u.*o|i.*a.*o.*e.*u|i.*a.*o.*u.*e|i.*a.*u.*e.*o|i.*a.*u.*o.*e|i.*e.*a.*o.*u|i.*e.*a.*u.*o|i.*e.*o.*a.*u|i.*e.*o.*u.*a|i.*e.*u.*a.*o|i.*e.*u.*o.*a|i.*o.*a.*e.*u|i.*o.*a.*u.*e|i.*o.*e.*a.*u|i.*o.*e.*u.*a|i.*o.*u.*a.*e|i.*o.*u.*e.*a|i.*u.*a.*e.*o|i.*u.*a.*o.*e|i.*u.*e.*a.*o|i.*u.*e.*o.*a|i.*u.*o.*a.*e|i.*u.*o.*e.*a|o.*a.*e.*i.*u|o.*a.*e.*u.*i|o.*a.*i.*e.*u|o.*a.*i.*u.*e|o.*a.*u.*e.*i|o.*a.*u.*i.*e|o.*e.*a.*i.*u|o.*e.*a.*u.*i|o.*e.*i.*a.*u|o.*e.*i.*u.*a|o.*e.*u.*a.*i|o.*e.*u.*i.*a|o.*i.*a.*e.*u|o.*i.*a.*u.*e|o.*i.*e.*a.*u|o.*i.*e.*u.*a|o.*i.*u.*a.*e|o.*i.*u.*e.*a|o.*u.*a.*e.*i|o.*u.*a.*i.*e|o.*u.*e.*a.*i|o.*u.*e.*i.*a|o.*u.*i.*a.*e|o.*u.*i.*e.*a|u.*a.*e.*i.*o|u.*a.*e.*o.*i|u.*a.*i.*e.*o|u.*a.*i.*o.*e|u.*a.*o.*e.*i|u.*a.*o.*i.*e|u.*e.*a.*i.*o|u.*e.*a.*o.*i|u.*e.*i.*a.*o|u.*e.*i.*o.*a|u.*e.*o.*a.*i|u.*e.*o.*i.*a|u.*i.*a.*e.*o|u.*i.*a.*o.*e|u.*i.*e.*a.*o|u.*i.*e.*o.*a|u.*i.*o.*a.*e|u.*i.*o.*e.*a|u.*o.*a.*e.*i|u.*o.*a.*i.*e|u.*o.*e.*a.*i|u.*o.*e.*i.*a|u.*o.*i.*a.*e|u.*o.*i.*e.*a
다음은 더 짧은 코드이지만 중첩으로 인해 이해하기가 더 어렵습니다.
a.*(e.*(i.*[ou]|o.*[iu]|u.*[io])|i.*(e.*[ou]|o.*[eu]|u.*[eo])|o.*(e.*[iu]|i.*[eu]|u.*[ei])|u.*(e.*[io]|i.*[eo]|o.*[ei]))|e.*(a.*(i.*[ou]|o.*[iu]|u.*[io])|i.*(a.*[ou]|o.*[au]|u.*[ao])|o.*(a.*[iu]|i.*[au]|u.*[ai])|u.*(a.*[io]|i.*[ao]|o.*[ai]))|i.*(a.*(e.*[ou]|o.*[eu]|u.*[eo])|e.*(a.*[ou]|o.*[au]|u.*[ao])|o.*(a.*[eu]|e.*[au]|u.*[ae])|u.*(a.*[eo]|e.*[ao]|o.*[ae]))|o.*(a.*(e.*[iu]|i.*[eu]|u.*[ei])|e.*(a.*[iu]|i.*[au]|u.*[ai])|i.*(a.*[eu]|e.*[au]|u.*[ae])|u.*(a.*[ei]|e.*[ai]|i.*[ae]))|u.*(a.*(e.*[io]|i.*[eo]|o.*[ei])|e.*(a.*[io]|i.*[ao]|o.*[ai])|i.*(a.*[eo]|e.*[ao]|o.*[ae])|o.*(a.*[ei]|e.*[ai]|i.*[ae]))
두 가지 모두 검색 중인 단어가 한 줄에 한 단어씩 있는 파일에 있다고 가정합니다. 그렇지 않은 경우 공백이 아닌 문자와 일치 .
하도록 모든 ''를 변경해야 합니다 . [^ ]
(참고: \S
from perl은 아마도 grep과 함께 사용하는 엔진을 포함하여 많은 정규식 엔진에서 작동하지만 Perl 호환 정규식은 표준 grep 기능이 아니므로 [^ ]
그래야 합니다.)
나는 이러한 정규식을 수동으로 작성하려고 시도하지 않을 것입니다. 첫 번째 코드에는 순열 생성기를 사용했고 두 번째 코드를 작성하기 위해 vim에서 많은 매크로 기록과 재생을 수행했습니다.
하지만 문제를 거꾸로 뒤집으면 어떤 일이 일어나는지 봅시다. 모든 모음이 포함된 문자열을 일치시키려고 하는 대신 반대쪽을 일치시켜 보십시오.모음이 하나 이상 누락되었습니다..
(이제부터는 입력 시 한 줄에 한 단어라는 가정을 고수합니다.)
a
일치하지 않는 단어 ^[^a]*$
(처음부터 끝까지의 문자 이외의 문자로 구성 a
)
e
일치가 누락된 단어 일치가 ^[^e]*$
누락된 i
단어 일치 ^[^i]*$
가 누락된 단어 일치 가 o
누락된 단어^[^o]*$
u
^[^u]*$
a
누락되거나 누락 e
되거나 누락 i
되거나 누락되거나 o
누락된 단어 u
가 일치합니다.
^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$
따라서 이 grep 명령은 원하지 않는 모든 단어를 제공합니다.
grep -E '^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$' wordlist
편리한 -v
옵션을 통해 원하는 단어를 얻을 수 있습니다하다생각하다:
grep -vE '^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$' wordlist
필요한 경우 추가하십시오 -i
.
정규식을 작성할 때 반전 기술을 염두에 두십시오. 때로는 매우 복잡한 정규식이 단순한 정규식과 반대되는 경우도 있습니다.
답변2
당신은하나의 grep
주문하다? 각 모음을 적어도 한 번(어떤 순서로든) 포함하는 모든 단어를 찾으려면 가장 간단한 명령은 다음과 같습니다.
쿼리단어 목록| grep 나 | grep 당신 |
-i
대소문자 구분이 필요한 경우 추가하세요.
답변3
grep
제 생각에는 이것은 실제 AND 연산자가 없기 때문에 약간 까다로운 질문입니다 . 다양한 트릭을 사용하여 grep
부분 AND를 얻을 수 있지만 일부 경우에만 작동합니다.
예를 들어, 와일드카드 연산자를 사용하여 문자열을 패턴과 일치시킬 수 있지만 패턴과 정확히 동일한 순서인 경우에만 일치합니다.
샘플 파일
$ cat words.txt
aeiou
a1e2i3o4u5
dog
blh
spkz
uoiea
1. .* 사용 예
$ grep -E ".*a.*e.*i.*o.*u.*" words.txt
aeiou
a1e2i3o4u5
aeiou
이는 동일한 시리즈의 시퀀스가 있는 문자열과만 일치합니다. 하지만 일치할 수 없습니다 uoiea
.
2. [aeiou] 사용 예
$ grep -E [aeiou] words.txt
aeiou
a1e2i3o4u5
dog
uoiea
이 방법은 일치할 수 있지만 너무 느슨하여 패턴에서 최소한 1개의 문자를 포함하는 모든 항목과 일치합니다.
3. 다중 grep 사용 예
$ grep a words.txt | grep e | grep i | grep o | grep u
aeiou
a1e2i3o4u5
uoiea
강제로 이것을 사용해야 grep
하고 목적이 그룹의 모든 문자를 일치시키는 것이라면 이것이 실제로 사용할 수 있는 유일한 옵션입니다.
4. awk 사용 예
$ awk '/a/ && /e/ && /i/ && /o/ && /u/ { print }' words.txt
aeiou
a1e2i3o4u5
uoiea
유닉스를 다룰 때 종종 그렇듯이. 올바른 도구로 전환하려는 의지가 있다면 불가능해 보이는 작업이 더 쉬워질 수 있습니다. 로 전환하면 awk
이제 실제 AND 연산자( &&
)를 사용할 수 있으며, 이제 찾고 있는 문자 집합을 지정할 수 있습니다.
grep
5. 기타 스위치 사용 예(-w)
일치하는 문자열이 모두 단일 단어로 보장되는 경우 이 -w
스위치를 사용할 수 있습니다.
-w, --word-regexp
Select only those lines containing matches that form whole words.
The test is that the matching substring must either be at the
beginning of the line, or preceded by a non-word constituent
character. Similarly, it must be either at the end of the line or
followed by a non-word constituent character. Word-constituent
characters are letters, digits, and the underscore.
따라서 집합의 일련의 문자가 [aeiou]
연속적인 한 다음과 같이 이 스위치를 활용할 수 있습니다.
$ grep -Ew "*[aeiou]*" words.txt
aeiou
uoiea
그러나 다중 사례 구문을 처리해야 하는 경우에도 실패할 것입니다.
$ echo "I love Fort Lauderdale" | grep -Ew "*[aeiou]*"
$
-i
그러나 대소문자를 구분하지 않는 스위치를 사용하면 grep
다시 작동합니다.
$ echo "I love Fort Lauderdale" | grep -Ewi "*[aeiou]*"
I love Fort Lauderdale