새 줄(\n)을 바꾸거나 제거하는 방법은 무엇입니까?

새 줄(\n)을 바꾸거나 제거하는 방법은 무엇입니까?

에만 액세스할 수 있습니다 busybox 1.27.2.

저는 현재 500,000개 이상의 단어와 6,000페이지가 넘는 사전 작업을 하고 있습니다(PDF에서 추출하고 Ghostscript를 사용하여 일반 텍스트로 변환). 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.

Ghostscript를 사용하여 추출이 완료된 후 일반 텍스트를 grep하면 다음과 같은 결과가 나옵니다(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)를 수행할 때 발생하며, greping하면 다음과 같은 결과를 얻습니다.


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 문자가 있어도 첫 번째 레코드와 동일하게 후속 레코드를 계속 처리합니다.

참고: 이는 전체 입력 파일이 메모리에 맞아야 함을 의미합니다. RAM이 16GB 이상인 최신 시스템에서는 문제가 되지 않을 것입니다. 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.

그러나 이렇게 하면 대시가 하이픈으로 처리됩니다(따라서 하이픈과 마찬가지로 줄 끝의 대시가 제거됩니다). 괄호 대신 대시를 사용하는 것도 드문 일이 아닙니다. "하이픈"이 더 이상 사용되지 않는다는 경고 메시지가 마음에 들지 않으면 \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

BEGINwhile(<>) { ..... }명령문은 스크립트 시작 부분, Perl -p이나 옵션을 사용하여 발생하는 암시적 루프(perl이 super 또는 각각 -n과 비슷하게 동작하게 만드는 ) 전후에 한 번 발생합니다 . 마찬가지로 명령문은 모든 입력을 읽고 처리한 후 스크립트 끝에서 한 번 발생합니다.sedsed -nEND

답변2

단일 스크립트에서 이 작업을 수행하려면 다음 패턴을 사용하는 것이 좋습니다 N;P;D.

sed -e ':loop' -e '$!N;/\n->/!s/-*\n/ /;tloop' -e 'P;D'

'다음' 줄을 추가하고 선택적 대시()를 사용하여 s/-*\n/ /새 줄이 시작될 때까지 줄 바꿈을 제거하는 반복 작업을 수행합니다 ->.

관련 정보