공백으로 구분된 단어가 포함된 텍스트 스트림이나 파일이 있습니다. 좋다:
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가 필요할 수 있는 여러 실행 없이는 이 작업을 수행할 수 없습니다 .
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
구문 분석하라는 요청은 위 코드처럼 , , , ... 대신 , 로 구문 분석하라는 요청과 충돌합니다 . (아마도 더 나은 예는 다음과 같습니다. 무엇이 되어야 할까요? 3개의 유니그램이 될까요, 아니면 4개의 유니그램이 될까요?)I
Am
A
Man
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
###########