
공백으로 구분된 단어가 포함된 텍스트 스트림이나 파일이 있습니다. 좋다:
I have a toy. you may not like it.
공백으로 구분된 각 단어는 두 개 이상의 작은 단어로 구성될 수 있으며, 낙타 표기(다른 대소문자로 구분), 뱀 표기(밑줄로 구분) 또는 점으로 구분됩니다. 예를 들면 다음과 같습니다.
I_amAManTest you_haveAHouse FOO_BAR_test.model
예를 들어:
I_amAManTest
그것은 나눌 수 있습니다 :
I
am
A
Man
Test
하지만 나는 매일 인쇄하고 싶어요.N복합어의 단어(연속되는 작은 단어의 각 하위 집합). 예:
I_amAManTest
산출:
// from first word on
I
I_am
I_amA
I_amAMan
I_amAManTest
// from second word on
am
amA
amAMan
amAManTest
// from third word on
A
AMan
AManTest
// from fourth word on
Man
ManTest
// from fifth word on
Test
요약하면 다음과 같은 입력에 대해
I_amAManTest you_haveAHouse FOO_BAR_test
출력은 다음과 같아야합니다.
I
I_am
I_amA
I_amAMan
I_amAManTest
am
amA
amAMan
amAManTest
A
AMan
AManTest
Man
ManTest
Test
you
you_have
you_haveA
you_haveAHouse
have
haveA
haveAHouse
A
AHouse
House
FOO
FOO_BAR
FOO_BAR_test
BAR
BAR_test
test
답변1
하나의 (주로) sed
솔루션:
cat "$@" |
tr -cs -- '._[:alpha:]' '[\n*]' |
sed -n -e 'h; :ms' \
-e 'p; :ss' \
-e 's/\([[:lower:]]\)[[:upper:]][[:lower:]]*$/\1/p; t ss' \
-e 's/\([[:lower:]]\)[[:upper:]][[:upper:]]*$/\1/p; t ss' \
-e 's/\([[:upper:]]\)[[:upper:]][[:lower:]]\+$/\1/p; t ss' \
-e 's/[._][[:alpha:]][[:lower:]]*$//p; t ss' \
-e 's/[._][[:upper:]]\+$//p; t ss' \
-e 'g' \
-e 's/^[[:upper:]]\?[[:lower:]]\+\([[:upper:]]\)/\1/; t mw' \
-e 's/^[[:upper:]]\+\([[:upper:]][[:lower:]]\)/\1/; t mw' \
-e 's/^[[:alpha:]][[:lower:]]*[._]//; t mw' \
-e 's/^[[:upper:]]\+[._]//; t mw' \
-e 'b' \
-e ':mw; h; b ms'
알고리즘은
for each compound word (e.g., “FOO_BAR_test”) in the input
do
repeat
print what you’ve got
repeat
remove a small word from the end (e.g., “FOO_BAR_test” → “FOO_BAR”) and print what’s left
until you’re down to the last one (e.g., “FOO_BAR_test” → “FOO”)
go back to what you had at the beginning of the above loop
and remove a small word from the beginning
(e.g., “FOO_BAR_test” → “BAR_test”) ... but don’t print anything
until you’re down to the last one (e.g., “FOO_BAR_test” → “test”)
end for loop
세부 사항:
cat "$@"
UUOC입니다. 나는 일반적으로 이것을 피하고 싶습니다. 이렇게 할 수는 있지만 여러 파일을 직접 전달할 수는 없습니다.tr args < file
tr
tr -cs -- '._[:alpha:]' '[\n*]'
예를 들어, 여러 복합어를 여러 줄로 나누세요.
~이 되다I_amAManTest you_haveAHouse FOO_BAR_test
따라서 sed는 한 번에 하나의 복합어를 처리할 수 있습니다.I_amAManTest you_haveAHouse FOO_BAR_test
sed -n
— 자동으로 아무것도 인쇄하지 않고 명령이 있을 때만 인쇄합니다.-e
다음을 지정하십시오.이자형xpression은 sed 스크립트의 일부입니다.h
- 패턴 공간을 예약된 공간으로 복사합니다.:ms
— 라벨(메인 루프의 시작)p
- 인쇄:ss
— 라벨(보조 루프 시작)- 다음 명령은 복합어의 끝에서 작은 단어를 제거하고 성공하면 결과를 인쇄하고 보조 루프의 시작 부분으로 다시 이동합니다.
s/\([[:lower:]]\)[[:upper:]][[:lower:]]*$/\1/p; t ss
— "nTest"를 "n"으로 변경합니다.s/\([[:lower:]]\)[[:upper:]][[:upper:]]*$/\1/p; t ss
— "mOK"를 "m"으로 변경합니다.s/\([[:upper:]]\)[[:upper:]][[:lower:]]\+$/\1/p; t ss
— "AMan"을 "A"로 변경합니다.s/[._][[:alpha:]][[:lower:]]*$//p; t ss
— "_am"을 제거합니다(아무 것도 대체하지 않음).s/[._][[:upper:]]\+$//p; t ss
— "_BAR"을 제거합니다(비어 있는 것으로 교체).
- 이것이 보조 루프의 끝입니다.
g
- 홀드 공간을 패턴 공간으로 복사합니다(위 루프의 시작 부분으로 돌아감).- 다음 명령은 복합어의 시작 부분에서 작은 단어를 제거하고, 성공하면 메인 루프의 끝으로 점프합니다(mw = 메인 루프 요약).
s/^[[:upper:]]\?[[:lower:]]\+\([[:upper:]]\)/\1/; t mw
— "amA"를 "A"로, "ManT"를 "T"로 변경합니다.s/^[[:upper:]]\+\([[:upper:]][[:lower:]]\)/\1/; t mw
— "AMa"를 "Ma"로 변경합니다.s/^[[:alpha:]][[:lower:]]*[._]//; t mw
— "I_" 및 "you_"를 제거합니다(아무 것도 대체하지 않음).s/^[[:upper:]]\+[._]//; t mw
— "FOO_"를 제거합니다(아무 것도 대체하지 않음).- 위의 각 대체 명령은 성공하면(뭔가 발견/일치하는 경우) 기본 루프 요약(아래)으로 이동합니다. 여기까지 오면 패턴 공간에는 작은 단어 하나만 포함되므로 작업은 끝난 것입니다.
b
— sed 스크립트 끝으로 분기(점프)합니다. 즉, sed 스크립트를 종료합니다.:mw
— 기본 루프 요약에 대한 레이블입니다.h
- 메인 루프의 다음 반복을 준비하기 위해 패턴 공간을 예약된 공간에 복사합니다.b ms
— 메인 루프의 시작 부분으로 점프합니다.
요청된 출력을 생성합니다. 안타깝게도 순서가 다릅니다. 중요한 내용이라면 수정하겠습니다.
$ echo "I_amAManTest you_haveAHouse FOO_BAR_test" | ./myscript
I_amAManTest
I_amAMan
I_amA
I_am
I
amAManTest
amAMan
amA
am
AManTest
AMan
A
ManTest
Man
Test
you_haveAHouse
you_haveA
you_have
you
haveAHouse
haveA
have
AHouse
A
House
FOO_BAR_test
FOO_BAR
FOO
BAR_test
BAR
Test
답변2
가장 좋은 방법은 아마도 Perl용 토크나이저 모듈을 찾는 것입니다. Grep은 여러 번 실행해야 하는 -P
PCRE(PCRE) 없이는 이 작업을 수행할 수 없습니다.
Perl 모듈이 없는 부분 솔루션은 다음과 같습니다.
while (<>) {
my $n = 1;
while (/(\S+)/g) {
printf "// outputting whitespace-separated word %d\n", $n++;
my $whole = $1;
while ($whole =~ /([a-zA-Z0-9][a-z]*+)/g) {
print "$1\n";
}
print "$whole\n"; # whole space-delimited tokens
}
}
표준 입력이나 파일에서 한 번에 한 줄씩 입력을 읽습니다. $n
주석의 단어 카운터를 인쇄한 다음 단어를 반복합니다(공백으로 구분되므로 정규식은 /(\S+)/g
공백이 아닌 연속 문자와 전체적으로 일치합니다). 각 단어에서 우리는 다음을 사용하여 토큰 부분을 반복합니다.([a-zA-Z0-9][a-z]*+)
, 일치 항목은 모두 숫자나 문자로 시작하고 그 뒤에 0개 이상의 소문자가 옵니다( *+
예: *
역추적을 비활성화하여재실행 서비스). 단어에서 일치하는 모든 토큰을 인쇄한 후 전체 단어를 인쇄합니다.
perl solution.pl intput.txt
다음과 같이 또는 인라인으로 실행할 수 있습니다 .
$ echo "I_amAManTest you_haveAHouse FOO_BAR_test.model" |perl solution.pl
// outputting whitespace-separated word 1
I
am
A
Man
Test
I_amAManTest
// outputting whitespace-separated word 2
you
have
A
House
you_haveAHouse
// outputting whitespace-separated word 3
F
O
O
B
A
R
test
model
FOO_BAR_test.model
여기에는 단어의 여러 부분 하위 표시가 부족합니다.
I_AmAMan
I
또한 , Am
, 로 확인되는 요청은 위 코드에서와 같이 , , , ...가 아닌 A
, 로 확인되는 요청과 충돌합니다 . Man
(아마도 더 나은 예는 다음과 같습니다. 어떻게 되어야 합니까? 3개의 단항 단어입니까 아니면 4개의 단어입니까?)FOO_BAR
FOO
BAR
F
O
O
B
I_AmOK
답변3
이것은 시작입니다. 대문자와 소문자의 혼합을 포함하는 문자열에 필요한 것이 무엇인지 파악하고 질문에 표시된 순서대로 출력을 인쇄하면 간단히 처리할 수 있습니다.
$ cat tst.awk
{
for (wordNr=1; wordNr<=NF; wordNr++) {
delete ngrams
word = $wordNr
ngrams[word]
print "word", word
numUndSeps = split(word,undSeps,/_/)
for (undSepNr=1; undSepNr<=numUndSeps; undSepNr++) {
undSep = undSeps[undSepNr]
ngrams[undSep]
print "undSep", undSep
numDotSeps = split(undSep,dotSeps,/[.]/)
for (dotSepNr=1; dotSepNr<=numDotSeps; dotSepNr++) {
dotSep = dotSeps[dotSepNr]
ngrams[dotSep]
print "dotSep", dotSep
while ( match(dotSep,/[[:upper:]]+[^[:upper:]]+/) ) {
camel = substr(dotSep,RSTART,RLENGTH)
dotSep = substr(dotSep,RSTART+RLENGTH)
ngrams[camel]
print "camel", camel
}
}
}
print "-----------"
for (ngram in ngrams) {
print ngram
}
print "###########"
}
}
.
$ awk -f tst.awk file
word I_amAManTest
undSep I
dotSep I
undSep amAManTest
dotSep amAManTest
camel AMan
camel Test
-----------
Test
amAManTest
I_amAManTest
I
AMan
###########
word you_haveAHouse
undSep you
dotSep you
undSep haveAHouse
dotSep haveAHouse
camel AHouse
-----------
you
you_haveAHouse
haveAHouse
AHouse
###########
word FOO_BAR_test.model
undSep FOO
dotSep FOO
undSep BAR
dotSep BAR
undSep test.model
dotSep test
dotSep model
-----------
model
FOO
FOO_BAR_test.model
test.model
BAR
test
###########