만 접근이 가능했습니다 busybox 1.27.2
.
저는 현재 50만 개가 넘는 단어와 6,000페이지가 넘는 사전(고스트스크립트가 포함된 PDF에서 추출되어 일반 텍스트로 변환됨)을 처리하고 있습니다. 파일 에 있습니다 20MB
.txt
. 원래 이 사전의 모든 단어에는 ->
단어를 더 쉽게 검색할 수 있도록 유도어가 있습니다.
내가 달성하려는 것은 그것을 *nix
친근하게 만드는 것입니다. 내가 이렇게 하면:
grep -e '->myfancyword' ./dictionary.txt
.
결과는 다음과 같습니다.
->fancyword: This is a very fancy word. *Definition going on for more than 6 lines*
모든 줄 바꿈을 제거하면 쉽게 수행할 수 있으므로 \n
모든 단어는 매우 긴 줄에 모든 정의를 갖게 됩니다. 괜찮습니다. 모든 \n
단어를 다음으로 대체 tr -d '\n'
한 다음 그 결과를 출력하여 sed 's/->/\n->/g'
한 줄에 모든 단어의 정의를 작성하게 됩니다. 이 거대한 문서에서도 5초도 안 되는 시간에 처리가 완료됩니다.
원하는 결과를 거의 얻고 있지만 완벽하지는 않습니다. 나는 이것을 할 수 grep -e '->word' ./dictionary.txt
있고 단어의 완전한 정의를 얻을 수 있습니다. 하지만 미용적으로는 완벽하지 않습니다.
출력이 마음에 들지 않는 이유는 원본 PDF가 A4
페이지에 인쇄되도록 형식이 지정되었기 때문입니다. 즉, 긴 단어가 있으면 잘립니다. 이와 같이:
예를 들어
->word: This is a defini-
tion.
이전 작업 흐름으로 파일을 처리하면 ->word: This is a defini- tion.
원하는 단어를 찾을 때 다음과 같은 결과가 나타납니다.
지금까지 내가 달성한 것은 다음과 같습니다.
- 입력
->firstword: This is a defini-
tion.
->secondword: This is a second defini-
tion.
적용된
tr -d '\n' < ./dictionary.txt > ./dictionary2.txt
출력은 다음과 같습니다
->firstword: This is a defini- tion. ->secondword: This is a second defini- tion.
실행:
sed -e 's/->/\n->/g' ./dictionary2.txt
다음으로 끝납니다:
산출
->firstword: This is a defini- tion.
->secondword: This is a second defini- tion.
-\n
두 번째 단계를 수행하기 전에 대시와 새 줄( )을 제거하여 잘린 모든 줄을 함께 "결합"하고 싶습니다 .
그래서 내 질문은: 줄 끝에 대시 -
와 개행 문자 \n
( ) 가 포함된 특정 문자열을 어떻게 대체/삭제할 수 있습니까 ?-\n
내가 얻고 싶은 것은 다음과 같습니다.
출력(대시와 공백( -
)이 더 이상 존재하지 않는지 확인하세요)
->firstword: This is a definition.
->secondword: This is a second definition.
감사합니다.
편집하다:
이것은 PDF 파일의 페이지입니다:
->abigeato. (Del lat. abigeatus). 1. m. Am. Hurto de ganado.
->abigeo. (Del lat. abigeus). 1. m. Am. Ladrón de ganado.
->abigotado, da. 1. adj. bigotudo.
->abinar. 1. tr. rur. y vulg. Binar la tierra.
->abintestato. (De ab intestato). 1. m. Der. Procedimiento judicial sobre herencia y
adjudicación de bienes de quien muere sin testar.
->abiogénesis. (De a-2, bio- y -génesis). 1. f. Producción hipotética de seres vivos par-
tiendo de materia inerte. 2. f. Bioquím. síntesis abiótica.
->abiótico, ca. 1. adj. Biol. Se dice del medio en que no es posible la vida. V. síntesis
abiótica
->abipón, na. 1. adj. Se dice del individuo de un pueblo amerindio que habitaba cerca del
Paraná. U. t. c. s. 2. adj. Perteneciente o relativo a los abipones. 3. m. Lengua de la familia
guaicurú hablada por los abipones.
->abisagrar. 1. tr. Clavar o fijar bisagras en las puertas y sus marcos, o en otros objetos.
->abisal. (Del lat. abyssus). 1. adj. abismal (|| perteneciente al abismo). 2. adj. Se dice de
las zonas del mar profundo que se extienden más allá del talud continental, y corresponden a
profundidades mayores de 2000 m. 3. adj. Perteneciente o relativo a tales zonas.
->abiselar. 1. tr. biselar.
->abisinio, nia. 1. adj. Natural de Abisinia, hoy Etiopía. U. t. c. s. 2. adj. Perteneciente o re-
lativo a este país de África. 3. m. Lengua abisinia. V. rito abisinio
->abismado, da. (Del part. de abismar). 1. adj. Dicho de una persona, de su expresión, de
su gesto, etc.: Ensimismados, reconcentrados. 2. adj. Heráld. Dicho de una pieza del escudo:
Puesta en el abismo.
->abismal (1). (Del ár. hisp. almismár, y este del ár. clás. mismar). 1. m. Cada uno de los
clavos con que se fijaba en el asta el hierro de la lanza.abismal2. 1. adj. Perteneciente o re-
lativo al abismo. 2. adj. Muy profundo, insondable, incomprensible.
->abismar. 1. tr. Hundir en un abismo. U. t. c. prnl. 2. tr. Confundir, abatir. U. t. c. prnl. 3.
prnl. Entregarse del todo a la contemplación, al dolor, etc. 4. prnl. Am. sorprenderse (|| con-
moverse con algo imprevisto o raro).
->abismático, ca. 1. adj. abismal2.
->abismo. (Quizá del lat. vulg. *abyssimus, der. de abyssus, y este del gr. , sin fondo). 1.
m. Profundidad grande, imponente y peligrosa, como la de los mares, la de un tajo, la de una
sima, etc. U. t. en sent. fig. Se sumió en el abismo de la desesperación. 2. m. infierno (|| lugar
de castigo eterno). 3. m. Cosa inmensa, insondable o incomprensible. 4. m. Diferencia
grande entre cosas, personas, ideas, sentimientos, etc. 5. m. Heráld. Punto o parte central
del escudo. 6. m. Nic. Maldad, perdición, ruina moral.
이것은 고스트스크립트(dos2unix로만 처리됨)를 사용하여 추출이 완료된 후 일반 텍스트를 가져오면 얻을 수 있는 것입니다.
grep -e '->abiog' ./rae-dos2unix.txt
->abiogénesis. (De a-2, bio- y -génesis). 1. f. Producción hipotética de seres vivos par-
이것은 텍스트에 대해 이전 단계(1-4)가 완료되었을 때입니다.
grep -e '->abiog' ./rae-una-linea.txt
->abiogénesis. (De a-2, bio- y -génesis). 1. f. Producción hipotética de seres vivos par- tiendo de materia inerte. 2. f. Bioquím. síntesis abiótica.
답변1
이것은 Perl에서는 매우 쉽습니다. Perl의 -0
옵션은 입력 레코드 구분 기호로 개행 문자 대신 NUL 문자를 사용하도록 지시하므로 입력에 NUL 문자가 없으면 전체 입력 파일을 하나의 레코드로 처리합니다. NUL 문자가 있더라도 첫 번째와 동일하게 후속 레코드를 계속 처리합니다.
참고: 이는 전체 입력 파일이 메모리에 맞아야 함을 의미합니다. 16GB 이상의 RAM이 있는 최신 시스템에서는 이는 문제가 되지 않습니다. RAM이 부족하지만 스왑이 충분한 구형 시스템에서는 여전히 작동하지만 속도가 훨씬 느려집니다.
$ cat input.txt
->firstword: This is a defini-
tion.
->secondword: This is a second defini-
tion.
$ perl -0 -p -e 's/-\s*\n//g' input.txt
->firstword: This is a definition.
->secondword: This is a second definition.
이렇게 하면 하이픈과 0개 이상의 공백 문자( \s
, 아래 참조), 개행 문자( \n
)의 순서가 모두 제거됩니다.
\s*
정규식의 일부는 후행 공백 문자와 일치하기 위해 존재합니다 .~할 것 같다줄 끝에 있어야 합니다. 내 경험상 텍스트 줄에 공백이 있는 것은 매우 흔한 일입니다(그리고 인쇄되지 않는 문자, 즉 보이지 않기 때문에 찾기가 어렵습니다). 또는 *
(0개 이상의공간문자) 또는 [ \t]*
(0개 이상의 공백 또는 탭) 또는 \h*
(0개 이상의 공백 또는 탭)수평의공백 문자) 대신 \s*
.
에서 man perlre
:
공백으로 간주되는 문자 집합은 유니코드에서 "패턴 공백"이라고 부르는 문자 집합입니다.
U+0009 CHARACTER TABULATION U+000A LINE FEED U+000B LINE TABULATION U+000C FORM FEED U+000D CARRIAGE RETURN U+0020 SPACE U+0085 NEXT LINE U+200E LEFT-TO-RIGHT MARK U+200F RIGHT-TO-LEFT MARK U+2028 LINE SEPARATOR U+2029 PARAGRAPH SEPARATOR
노트:
- 문자
-
는 사용 가능한 유일한 "하이픈" 또는 "대시" 문자가 아닙니다. Wikipedia에는 유니코드를 나열하는 페이지가 있습니다.하이픈그리고대시문자. 다행스럽게도 Perl에는 우수한 유니코드 처리 기능이 있으므로 대시 범주 문자를 모두 일치시키는 대신\p{Dash}
(또는 ) 을 사용하도록 한 줄짜리 코드를 다시 작성할 수 있습니다 .\p{Pd}
-
$ perl -0 -p -e 's/\p{Dash}\h*\n//g' input.txt
->firstword: This is a definition.
->secondword: This is a second definition.
그러나 이렇게 하면 em-대시가 하이픈과 동일하게 처리됩니다(따라서 하이픈과 마찬가지로 줄 끝에서 em-대시가 제거됩니다). 그리고 괄호 대신 em-대시를 사용하는 것도 드문 일이 아닙니다. . "하이픈"이 더 이상 사용되지 않는다는 경고 메시지가 마음에 들지 않으면 \p{Hyphen}
대신 사용할 수 있습니다 . \p{Dash}
또는 하이픈으로 처리하려는 유니코드 코드 포인트만 포함하는 대괄호 표현식을 사용할 수 있습니다. 예:
perl -0 -p -e 's/[\N{U+002D}\N{U+00AD}\N{U+2010}\N{U+2011}]\h*\n//g' input.txt
로 시작하는 각 단어 정의를 사용하지 않는 것이 좋습니다
->
. 그러면 grep을 사용하여 단어를 검색하는 것이 불필요하게 어색해집니다. 검색 문자열은 (>
쉘이 리디렉션에 사용하는 로 인해) 인용되어야 하고--
(로 인해) 앞에 와야-
합니다. 그렇지 않으면 grep은 검색 패턴을 다음과 같이 처리합니다. 옵션으로 사용하려는 경우). 예를 들어 다음과 같은 작업은 수행할 수 없습니다.grep ^firstword: dictionary.txt
대신 다음을 수행해야 합니다.
grep -- '^->firstword:' dictionary.txt
더 나은 예를 들어 이미지에서 텍스트를 추출했습니다.tesseract-ocr뒤에 오지 않는 모든 개행 문자도 제거하는 perl one-liner 버전을 통해 실행하십시오 ->
.
$ cat input2.txt
->abigeato. (Del lat. abigeatus). 1. m. Am. Hurto de ganado.
->abigeo. (Del lat. abigeus). 1. m. Am. Ladrén de ganado.
->abigotado, da. 1. adj. bigotudo.
->abinar. 1. tr. rur. y vulg. Binar la tierra.
->abintestato. (De ab intestato). 1. m. Der. Procedimiento judicial sobre herencia y
adjudicacion de bienes de quien muere sin testar.
Eiiftiénesis. (De a-2, bio- y -génesis). 1. f. Produccién hipotética de seres vivos par-
tiendo de materia inerte. 2. f. Bioquim. sintesis abistica,
->abidtico, ca. 1. adj. Biol. Se dice del medio en que no es posible la vida. V. sintesis
abidtica
->abipon, na. 1. adj. Se dice del individuo de un pueblo amerindio que habitaba cerca del
Parana. U. t.c. s. 2. adj. Perteneciente o relativo a los abipones. 3. m. Lengua de la familia
guaicurt hablada por los abipones.
->abisagrar. 1. tr. Clavar o fijar bisagras en las puertas y sus marcos, 0 en otros objetos.
->abisal. (Del lat. abyssus). 1. adj. abismal (|| perteneciente al abismo). 2. adj. Se dice de
las zonas del mar profundo que se extienden mas alla del talud continental, y corresponden a
$ perl -0 -p -e 's/[\N{U+002D}\N{U+00AD}\N{U+2010}\N{U+2011}]\h*\n//g; s/\n+(?!->)//g' input2.txt
->abigeato. (Del lat. abigeatus). 1. m. Am. Hurto de ganado.
->abigeo. (Del lat. abigeus). 1. m. Am. Ladrén de ganado.
->abigotado, da. 1. adj. bigotudo.
->abinar. 1. tr. rur. y vulg. Binar la tierra.
->abintestato. (De ab intestato). 1. m. Der. Procedimiento judicial sobre herencia yadjudicacion de bienes de quien muere sin testar.Eiiftiénesis. (De a-2, bio- y -génesis). 1. f. Produccién hipotética de seres vivos partiendo de materia inerte. 2. f. Bioquim. sintesis abistica,
->abidtico, ca. 1. adj. Biol. Se dice del medio en que no es posible la vida. V. sintesisabidtica
->abipon, na. 1. adj. Se dice del individuo de un pueblo amerindio que habitaba cerca delParana. U. t.c. s. 2. adj. Perteneciente o relativo a los abipones. 3. m. Lengua de la familiaguaicurt hablada por los abipones.
->abisagrar. 1. tr. Clavar o fijar bisagras en las puertas y sus marcos, 0 en otros objetos.
->abisal. (Del lat. abyssus). 1. adj. abismal (|| perteneciente al abismo). 2. adj. Se dice delas zonas del mar profundo que se extienden mas alla del talud continental, y corresponden a
->
최종 출력 파일에서 시퀀스를 제거하는 것이 좋습니다 . 텍스트를 처리하는 동안에는 유용한 마커이지만 나중에는 문제가 됩니다.
@zevzek의 의견은 "엄청난 양의 RAM 사용" 문제를 해결합니다. 입력 레코드 구분자로 NUL을 사용하는 대신 ->
구분자로 사용하십시오. 이렇게 하면 Perl 스크립트가 한 번에 전체 파일을 읽는 대신 한 번에 하나의 단어 정의만 읽게 됩니다. 이렇게 하면 사용 가능한 RAM을 모두 사용하지 않고 시스템이 스왑되기 때문에 매우 큰 입력 파일로 훨씬 더 빠르게 실행됩니다.
이제 스크립트를 표시하는 문자 시퀀스를 처리하고 있으므로 스크립트에 다른 변경 사항이 필요합니다.시작새로운 단어 정의의끝이전 정의의 구체적으로 다음을 수행해야 합니다.
- 명령줄 옵션
-p
(항상 현재 레코드 출력)을-n
(지정한 경우에만 현재 레코드 출력)로 변경합니다. - 줄 끝 문자를 제거합니다(Perl의
chomp()
기능이 이를 수행합니다). - 이제 입력 레코드가 비어 있거나 공백만 포함되어 있는지 확인하십시오.상상의첫 번째 실제 레코드 "abigeato" 앞에 빈 레코드가 있고 우리는 그것을 인쇄하고 싶지 않습니다. (갑자기 가상의 빈 레코드가 나타나는 이유는 무엇입니까?
->
이제 새 레코드의 시작이 아니라 레코드의 끝을 나타내기 때문입니다. in은->
이전->abigeato
(빈) 레코드와 새 "abigeato" 레코드 사이의 구분 기호입니다.) - "->"와 줄 바꿈을 사용하여 수정된 레코드를 인쇄합니다.
모두 합쳐서 최종 한 줄짜리 내용이 다음과 같이 변경됩니다.
$ perl -0 -p -e 's/[\N{U+002D}\N{U+00AD}\N{U+2010}\N{U+2011}]\h*\n//g;
s/\n+(?!->)//g' input2.txt
이에:
perl -n -e 'BEGIN { $/="->" };
chomp;
next if m/^\s*$/;
s/[\N{U+002D}\N{U+00AD}\N{U+2010}\N{U+2011}]\h*\n//g;
s/\n+//g;
print "->$_\n"' input2.txt
이 버전의 출력은 최종 출력 행이 개행 문자( )로 끝나는 것을 제외하고는 원본과 동일합니다 \n
. 원본은 이를 보장하지 않았으며 실제로 뒤에 오지 않는 모든 개행 문자를 제거하여 이를 방지했습니다 ->
. 기술적으로 모든 단일 줄이 ....로 끝나는 경우 파일은 유닉스의 텍스트 파일일 뿐이므로 이는 무료 보너스입니다. \n
대부분의 경우 이는 중요하지 않습니다(적어도 최신 버전의 표준 텍스트 처리 도구에서는 제외). 로 끝나지 않지만 일부 프로그램은 "텍스트 파일"의 마지막 줄을 올바르게 처리하지 못합니다 \n
.
(그런데 END 블록을 추가하여 출력 끝에 개행 문자를 다시 추가하면 원본을 수정할 수 있습니다. END { print "\n" }
)
$/
는 의 변수 와 유사하게 입력 레코드 구분 기호를 정의하는 Perl 변수입니다( man perlvar
Perl의 사전 정의/특수/제어 변수에 대한 자세한 내용은 참조) . 이전에는 Perl의 옵션을 사용하여 NUL 문자로 설정했습니다( Perl의 명령줄 옵션에 대한 자세한 내용은 참조).RS
awk
-0
man perlrun
BEGIN
명령문은 스크립트 시작 부분에서 while(<>) { ..... }
Perl -p
이나 -n
옵션을 사용하여 발생하는 암시적 루프(perl이 각각 초강력 sed
또는 sed -n
각각처럼 작동하도록 만드는) 암시적 루프 전후에서 한 번 발생합니다. 마찬가지로 END
명령문은 모든 입력을 읽고 처리한 후 스크립트 끝에서 한 번 발생합니다.
답변2
다음 패턴을 사용하여 단일 스크립트로 수행하는 것이 좋습니다 N;P;D
.
sed -e ':loop' -e '$!N;/\n->/!s/-*\n/ /;tloop' -e 'P;D'
s/-*\n/ /
새 줄이 로 시작될 때까지 'N'ext 줄을 추가하고 선택적 대시( )를 사용하여 줄 바꿈을 제거하는 과정을 반복합니다 ->
.