Ubuntu에서 다음 문제를 해결하는 방법을 아는 사람이 있습니까? 텍스트 파일에 문자열이 있습니다. 가장 긴 부분 문자열을 찾는 방법에스~에에스자체가 원래 문자열의 하위 문자열로 연결됩니까?
예를 들어 원래 문자열이 이면 hfhfggccaggccagccafff
출력은 이어야 합니다 ggcca
. 하지만 원래 문자열의 길이가 약 700,000자라면 어떤 종류의 프로그램이나 스크립트가 작동할까요?
내 노력은 파이썬 스크립트입니다
import re
s = 'hfhfggccaggccagccafff'
def find(s):
r=max(re.findall(r'((\w+?)\2+)', s), key=lambda t: len(t[0]))
return r
print(find(s))
답변1
GNU grep을 사용하십시오:
echo hfhfggccaggccagccafff |
grep -Po '(.*)\K\1' | awk 'length > l {l=length;s=$0} END{print s}'
ggcca
물론 이로 인해 시퀀스가 겹치지는 않습니다.
답변2
$ sed -n -f <( awk '{ for (i = int(length/2) + 1; i > 0; --i) printf "s/.*\\(.\\{%d\\}\\)\\1.*/\\1/p;t\n", i }' file ) file
gccag
awk
이는 많은 명령문을 생성 하는 데 사용됩니다 sed
. 각 문은 특정 길이의 반복되는 하위 문자열을 찾기 위해 일치 항목을 시도하고, 그렇게 하는 경우 스크립트를 종료합니다(또는 이전 명령이 대체를 수행한 경우 sed
스크립트 끝으로 분기 ).t
s///
지정된 데이터에 대해 sed
다음 스크립트가 생성됩니다.
s/.*\(.\{11\}\)\1.*/\1/p;t
s/.*\(.\{10\}\)\1.*/\1/p;t
s/.*\(.\{9\}\)\1.*/\1/p;t
s/.*\(.\{8\}\)\1.*/\1/p;t
s/.*\(.\{7\}\)\1.*/\1/p;t
s/.*\(.\{6\}\)\1.*/\1/p;t
s/.*\(.\{5\}\)\1.*/\1/p;t
s/.*\(.\{4\}\)\1.*/\1/p;t
s/.*\(.\{3\}\)\1.*/\1/p;t
s/.*\(.\{2\}\)\1.*/\1/p;t
s/.*\(.\{1\}\)\1.*/\1/p;t
일치하는 항목이 발견될 때까지 반복의 길이가 내림차순으로 테스트됩니다.
sed
매우 긴 줄에서 이것을 테스트하지는 않았지만 (및 )에 대한 입력은 "텍스트 파일"로 제한되고 "텍스트 파일"은 POSIX가 "at"로 정의하는 grep
최대 문자 줄이 있는 파일이라는 것을 알았습니다. LINE_MAX
최소" 2048(우분투에서의 실제 값이기도 합니다). 또한 수정자에 사용되는 수에는 제한이 있습니다 \{n\}
.