새 줄(\n)을 대체/삭제하는 방법은 무엇입니까?

새 줄(\n)을 대체/삭제하는 방법은 무엇입니까?

만 접근이 가능했습니다 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.원하는 단어를 찾을 때 다음과 같은 결과가 나타납니다.

지금까지 내가 달성한 것은 다음과 같습니다.

  1. 입력
->firstword: This is a defini-
tion.
->secondword: This is a second defini-
tion.
  1. 적용된 tr -d '\n' < ./dictionary.txt > ./dictionary2.txt

  2. 출력은 다음과 같습니다

->firstword: This is a defini- tion. ->secondword: This is a second defini- tion.
  1. 실행:sed -e 's/->/\n->/g' ./dictionary2.txt

  2. 다음으로 끝납니다:

산출

->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

노트:

  1. 문자 -는 사용 가능한 유일한 "하이픈" 또는 "대시" 문자가 아닙니다. 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
  1. 로 시작하는 각 단어 정의를 사용하지 않는 것이 좋습니다 ->. 그러면 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 perlvarPerl의 사전 정의/특수/제어 변수에 대한 자세한 내용은 참조) . 이전에는 Perl의 옵션을 사용하여 NUL 문자로 설정했습니다( Perl의 명령줄 옵션에 대한 자세한 내용은 참조).RSawk-0man 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 줄을 추가하고 선택적 대시( )를 사용하여 줄 바꿈을 제거하는 과정을 반복합니다 ->.

관련 정보