![grep은 고유한 대문자 문구를 추출합니다.](https://linux55.com/image/196446/grep%EC%9D%80%20%EA%B3%A0%EC%9C%A0%ED%95%9C%20%EB%8C%80%EB%AC%B8%EC%9E%90%20%EB%AC%B8%EA%B5%AC%EB%A5%BC%20%EC%B6%94%EC%B6%9C%ED%95%A9%EB%8B%88%EB%8B%A4..png)
다음 코드 조각은 입력 텍스트의 모든 대문자 목록을 생성합니다.
grep -o '[^ ]*[[:upper:]][^ ]*' book_text.txt > Capitalized_words.txt
이제 길이에 상관없이 대문자로 표시된 고유한 문구의 발생 횟수를 추출하고 계산하고 싶습니다.
즉, 대문자 첫 글자를 공유하는 공백으로 구분된 단어의 고유한 문자열 수를 원합니다. 제공된 유일한 문구에는 구두점이나 대문자가 아닌 단어가 포함되어 있지 않으므로 두 문구 및 가 University of British Columbia
됩니다 .University
British Columbia
입력 예:
Harvard archaeologists in Mexico also participated in the International
School of American Archaeology and Ethnology in Mexico City with scholars from
Mexico, Prussia and the United States.
예상 출력:
1 - Harvard
1 - International School
1 - American Archaeology
1 - Ethnology
1 - Mexico City
2 - Mexico
1 - Prussia
1 - United States
예에서 Mexico
및 는 Mexico City
단어를 공유하는 서로 다른 두 개의 고유한 구문입니다.
답변1
GNU grep
PCRE를 사용하여 빌드하는 경우 다음을 지원합니다.
$ grep -Pow '(\p{Lu}\w*)(\s+(?1))*' input | sort | uniq -c
1 American Archaeology
1 Ethnology
1 Example Input
1 Harvard
1 International School
2 Mexico
1 Mexico City
1 Prussia
1 United States
또는:
<input tr -s '[:space:]' '[ *]' |
grep -Pow '(\p{Lu}\w*)(\s+(?1))*' |
sort |
uniq -c
공백 문자(개행 문자 포함)의 모든 시퀀스는 먼저 단일 공백(예 Example Input
: Example Input
또는 )Example\nInput
으로 변환됩니다.
-w
해당 사항이 아니니 참고해주세요공간 분리단어, 단어 경계는 단어와 단어가 아닌 문자 사이에 있습니다(단어 문자는 숫자와 밑줄입니다). 너 원한다고 했지? 공백으로 구분된 단어United States
이지만 이는 대신 United States.
또는 Mexico
대신에 입력을 기대하는 것과 충돌합니다 .Mexico, Prussia
또한 [^ ]*[[:upper:]][^ ]*
공백으로 구분된 단어와 일치합니다.포함하다대문자가 하나 이상 있지만 시작 부분에 있을 필요는 없습니다. 예를 들어, fooBar
또는 와 일치합니다 0xAB+12
. (?<!\S)\p{Lu}\S*
대문자로 시작하는 공백으로 구분된 단어가 필요합니다 .
$ grep -Po '(?<!\S)(\p{Lu}\S*)(\s+(?1))*' input | sort | uniq -c
1 American Archaeology
1 Ethnology
1 Example Input:
1 International School
1 Mexico
1 Mexico City
1 Mexico, Prussia
1 United States."
( Harvard
전체 줄이 있어서 공백 Example Input: "Havard ..."
으로 구분된 단어가 대문자로 시작하지 않기 때문에 누락되었습니다.)input
"Harvard
in
중간에 일부 와 을 추가할 수도 있습니다 .of
$ grep -Pow '(\p{Lu}\w*)((\s+(in|of))?\s+(?1))*' input | sort | uniq -c
1 Ethnology in Mexico City
1 Example Input
1 Harvard
1 International School of American Archaeology
2 Mexico
1 Prussia
1 United States
\w
영어가 아닌 텍스트를 다루는 경우 로 바꿀 수도 있습니다 ((?=\w)\X)
. 즉,단어 문자, 일치단어 문자로 시작하는 문자소 클러스터.
$ echo $'Universidad Nacional Auto\u0301noma de Me\u0301xico' |
grep -Pow '(\p{Lu}\w*)((\s+(in|of|de))?\s+(?1))*' | sort | uniq -c
1 Me
1 Universidad Nacional Auto
$ echo $'Universidad Nacional Auto\u0301noma de Me\u0301xico' |
grep -Pow '((?=\p{Lu})\X((?=\w)\X)*)((\s+(in|of|de))?\s+(?1))*' |
sort | uniq -c
1 Universidad Nacional Autónoma de México
Bar
에서는 여전히 일치합니다 $'foo\u0301Bar'
.
또한 단어 문자/자소 및/또는 구분 기호로 덮을 이름의 구성을 구체화해야 할 수도 있습니다.수지의 부엌,오브라이언 초등학교,장 폴 사르트르 고등학교, 등.
이 모든 것을 종합하면 다음과 같이 끝납니다.
first_grapheme='(?: (?= \p{Lu} ) \X )'
word_character="[\w'-]"
word_grapheme="(?: (?= $word_character ) \X )"
word="$first_grapheme $word_grapheme *"
separator='(?: [ ] (?: in | on | of | de | en ) )? [ ]'
<input tr -s '[:space:]' '[ *]' |
grep -Po "(?x) (?<! \pM | $word_character ) $word (?: $separator $word ) *" |
sort |
uniq -c
답변2
Raku(이전 Perl_6) 사용
raku -e '.subst(",", " and ", :g).subst(".", " ", :g).comb(/ <( [ <:Lu> <:Ll>+ \h+ ]+ )> <:Ll>* /).map(*.trim-trailing).Bag.antipairs.join("\n").say for lines();'
입력 예:
Harvard archaeologists in Mexico also participated in the International School of American Archaeology and Ethnology in Mexico City with scholars from Mexico, Prussia and the United States.
출력 예(최종):
1 Ethnology
1 Prussia
2 Mexico
1 American Archaeology
1 Harvard
1 Mexico City
1 International School
1 United States
흥미로운 질문은 Raku가 상당히 발전된 정규식 엔진(하단 참조에 따르면 PCRE보다 더 발전됨)을 가지고 있다고 간주되기 때문에 Raku를 사용하여 이 문제를 해결하기로 결정했습니다.
Raku 코드를 세 가지 주요 부분으로 나누는 것부터 시작할 수 있습니다. 이 comb
부분에서는 정규식 일치자를 사용하여 텍스트 입력을 필수 요소로 나눕니다. 여러분은 이미 많은 기호(또는 개념)에 익숙할 수 있습니다. 예를 들어 Raku의 캡처 태그는 입니다 <(…)>
. 이 부분만 1을 반환했지만 이 comb
부분만 예상 값인 8/9를 반환했습니다.
raku -e '.comb(/ <( [ <:Lu> <:Ll>+ \h+ ]+ )> <:Ll>* /).join("\n").say for lines();'
출력 예(시도 #1):
Harvard
Mexico
International School
American Archaeology
Ethnology
Mexico City
Prussia
United
Mexico,
값 과 부분 값이 모두 States.
그대로 남아 있기 때문에 구두점에 대해 조치를 취해야 한다는 것을 즉시 알 수 있습니다 . 두 번째 시도:
raku -e '.subst(",", " and ", :g).subst(".", " ", :g).comb(/ <( [ <:Lu> <:Ll>+ \h+ ]+ )> <:Ll>* /).join("\n").say for lines();'
출력 예(시도 #2):
Harvard
Mexico
International School
American Archaeology
Ethnology
Mexico City
Mexico
Prussia
United States
위는 예상 값인 9/9를 반환합니다. 마지막으로 쉼표를 로, 마침표를 공백으로 ,
바꾸기로 결정했습니다 . (텍스트에 대한 최선의 조치를 결정해야 합니다).and
.
상단의 최종 결과를 얻으려면 .map(*.trim-trailing).Bag.antipairs
원하는 결과를 생성하는 코드에 호출이 삽입됩니다.
https://slides.yowconference.com/yowwest2015/Conway-EverythingYouKnowAboutRegexesIsWrong.pdf
https://youtu.be/ubvSjW6Nyqk
https://raku.org