단일 줄 바꿈 만 바꾸는 더 좋은 방법이 있어야합니까?


27

나는 일반적으로 LaTex에 물건을 컴파일하거나 줄 바꿈이 무시되는 다른 형식으로 쓰고 있기 때문에 문장 당 한 줄을 쓰는 습관이 있습니다. 빈 줄을 사용하여 새 단락의 시작을 나타냅니다.

이제이 스타일로 작성된 파일을 일반 텍스트로 보내려고합니다. 모든 단일 줄 바꿈을 제거하고 싶지만 이중 줄 바꿈은 그대로 두십시오. 이것이 내가 한 일입니다.

sed 's/$^/NEWLINE/' file.txt | awk '{printf "%s ",$0}' | sed 's/NEWLINE/\n\n/g' > linebreakfile.txt

이것은 빈 줄을 파일에 표시되지 않는다고 확신하는 텍스트로 바꿉니다. NEWLINE그런 다음 모든 줄 바꿈을 awk (일부 웹 사이트에서 해당 트릭을 찾았습니다)를 제거한 다음NEWLINE s를 필수 두 .

이것은 꽤 간단한 일을하는 긴 바람처럼 보입니다. 더 간단한 방법이 있습니까? 또한 여러 공간 (어떤 이유로 들어 오는 경우)을 단일 공간으로 바꾸는 방법이 있다면 좋을 것입니다.

나는 emacs를 사용한다. 그래서 emacs 특유의 트릭이 있다면, 순수한 sed 또는 pure awk 버전을 보게 될 것이다.


첫 번째 sed 명령에서 $ ^가 아니라 ^ $를 의미했습니다.
사용자 알 수 없음

@ user 예, 그렇습니다.
Seamus

줄 바꿈을 모두 제거하는 더 쉬운 방법 : tr -d "\n".
jfg956

답변:


18

다음과 같이 awk를 사용할 수 있습니다.

$ awk ' /^$/ { print; } /./ { printf("%s ", $0); } ' test

또는 끝에 추가 줄 바꿈이 필요한 경우 :

$ awk ' /^$/ { print; } /./ { printf("%s ", $0); } END { print ""; } ' test

또는 개행으로 단락을 구분하려면 다음을 수행하십시오.

$ awk ' /^$/ { print "\n"; } /./ { printf("%s ", $0); } END { print ""; } ' test

이 awk 명령은 패턴으로 보호되는 조치를 사용합니다.

/regex/

또는

END

다음 조치는 패턴이 현재 행과 일치하는 경우에만 실행됩니다.

그리고 ^$.문자는 정규식에서 특별한 의미를 가지며, 여기서 ^줄의 시작, $끝 및 .임의의 문자 와 일치합니다 .


단락 사이에 빈 줄 을 유지 하고 싶지만 이것은 좋습니다 . 첫 번째 인쇄 명령에 새로운 줄을 추가하여 이와 같은 작업을 수행 할 수 있다고 가정합니까? 또한, 무엇을한다 /./일 : 그것은 같이하고 행동하는 것 같다 else에 대한 /^$/문자열 일치, 그 권리는?
Seamus 2019

1
@Seamus, 반드시-첫 번째 인쇄를 바꾸십시오 (답변이 업데이트되었습니다)-/./는 적어도 한 문자 길이 인 모든 줄과 일치합니다. 즉, 빈 줄과 일치하는 / ^ $ / 패턴의 보완.
maxschlepzig

9

Awk 또는 Perl의 단락 모드 를 사용하여 단락별로 파일 단락을 처리합니다. 여기서 단락은 빈 줄로 구분됩니다.

awk -vRS= '
  NR!=1 {print ""}      # print blank line before every record but the first
  {                     # do this for every record (i.e. paragraph):
    gsub(" *\n *"," "); # replace newlines by spaces, compressing spaces
    sub(" *$","");      # remove spaces at the end of the paragraph
    print
  }
'
perl -000 -pe '             # for every paragraph:
  print "\n" unless $.==1;  # print a blank line, except before the first paragraph
  s/ *\n *(?!$)/ /g;        # replace newlines by spaces, compressing spaces, but not at the end of the paragraph
  s/ *\n+\z/\n/             # normalize the last line end of the paragraph
'

물론 이것은 (La) TeX를 구문 분석하지 않기 때문에 주석, 말 그대로 환경 및 기타 특수 구문을 끔찍하게 손상시킵니다. DeTeX 또는 다른 (La) TeX- 텍스트 변환기 를 살펴볼 수 있습니다 .


8

sed 솔루션

$ sed -e ':a;N;$!ba;s/\(.\)\n/\1 /g' -e 's/\n/\n\n/' test.text

이 솔루션 :a에서는 레이블을 작성하고 a명령을 사용하지 않습니다 .

여러 공간 교체

사용 tr:$ tr -s ' ' <test.text


8

내가 올바르게 이해했다면 빈 줄은 두 개의 연속적인 줄 바꿈을 의미 \n\n합니다.

그렇다면 가능한 한 가지 해결책은 줄 바꿈의 모든 단수 발생을 제거하는 것입니다.

Perl에서 미리보기 어설 션은이를 달성하는 한 가지 방법입니다.

$ perl -0777 -i -pe 's/\n(?=[^\n])//g' test
  • -0777플래그 효과적으로 하나의 문자열로 전체 파일을 slurps
  • -p 펄에게 기본적으로 작업중 인 문자열을 인쇄하도록 지시합니다.
  • -i 전체 편집을 지정합니다
  • 전역 일치는 모든 단일 줄 바꿈 발생을 처리합니다.

이것이 가지고있는 한 가지 문제는 문장 사이에 공백이 없다는 것입니다.
Steven D

6

(고대 질문의 부활)

이것은 정확히 것 같다 fmtpar단락 재 포맷 -에 대한 것입니다. 당신처럼 (그리고 많은 프로그램처럼) 그들은 단락 경계를 하나 이상의 빈 줄로 정의합니다. 이 중 하나를 통해 텍스트를 파이핑 해보십시오.

fmt 표준 유닉스 유틸리티이며 GNU Coreutils에서 찾을 수 있습니다.

parfmtAdam M. Costello가 작성 하여 크게 개선 한 것으로 http://www.nicemice.net/par/ 에서 찾을 수 있습니다 (데비안을 포함한 여러 배포판에도 패키지되어 있음-1996 년 1 월 데비안 용 패키지, pkg에 대한 새로운 관리자가 있지만).


6
sed -e'/./{H;$!d;}' -e'x;s/\n//g'

sedH하나 이상의 문자를 포함하는 모든 행을 이전 공간에 추가합니다 . 그것은 바로 d그 곳을 제외하고는 모두 마지막 순간을 제외한 모든 사람들을 끌어들입니다. 남아있을 수있는 유일한 행은 공백이며, sede x가 보류 및 패턴 공간을 변경하고 누적 된 모든 \newline 문자를 삭제할 때이 행에 있습니다.

<tabs> 또는 <spaces> 만 포함 된 행을 공백 으로 간주하려면 /./위 의 주소를로 바꾸십시오 /[^[:blank:]]/. 공간을 쥐어 짜려면 다음을 수행하십시오.

 sed -e'/./{H;$!d;}'    \
     -e'x;s/\n//g'      \
     -e's/\([[:blank:]]\)*/\1/g'

5

Gilles의 perl과 awk 간결한 예제를 본 후, 나는 이것을 게시하는 것을 꺼려했지만 이미 연습을 마쳤으며 기능적인 스크립트이며 합리적으로 문서화되어 있습니다. 이 점만으로도 일부 사람들이 관심을 가질 수 있습니다.

이 스크립트는 공백이 포함되어 있어도 빈 줄을 공백으로 간주합니다.
텍스트의 여러 공백이 단일 공백으로 압축됩니다.
텍스트 행에서 후행 공백이 제거됩니다. 연속적인 빈 줄은 한 줄로 축소됩니다. 스크립트는 맨 위와 맨 아래의 빈 줄을 그대로 둡니다.

가장 사소한 스크립트 이외의 다른 경우에는 sed를 별도의 스크립트 파일로 구조화 된 형태로 훨씬 쉽게 작성할 수 있습니다. 다음은 그러한 예입니다.

확장 정규식 구문
호출 사용 : $ sed -rf script text-file

  :first-empty-line
  #================
  /^[[:space:]]*$/ { # if pattern-space is empty...
      $q  # last line # flush-quit 
      n   # pattern-flush=nextline-continue

      :subsequent-empty-line
      #=====================
      /^[[:space:]]*$/ { # if pattern-space is empty...
          $d        # last line # pattern-delete-cycle
          N         # pattern+=nl+nextline
          s/.*\n//  # scrap the leading 'blank' line
          t subsequent-empty-line # branch-on-substitute
      }
  }

  :text-line
  #=========
  $q                       # last line # flush-quit 
  s/^(.*)[[:space:]]*/\1/  # trim trailing whitespace
  s/ +/ /g                 # condense mulltiple spaces
  N                        # pattern+=nl+nextline
  /^.*\n[[:space:]]*$/ { # if newly-read line is blank 
      P          # pattern-first-line-print
      s/^.*\n//  # remove the leading 'text' line
      t first-empty-line   # branch-on-substitute
  }
  # read line is text
  s/\n/ /      # replace \n with a space
  t text-line  # branch-on-substitute

참고 : flush주석에서 의미 : 패턴 공간을 sed의 내부 stdout 처리로 보냅니다. stdout에 대한 명확한 인쇄를 의미하지는 않습니다. 출력은 sed의 -n옵션 에 따라 다릅니다 . 예. q명령 수단의 높이를 종료하지 않고 두 조각을 비교 ... : echo x |sed -e q인쇄 X, echo x |sed -ne q인쇄 아무것도의 사용 반면 p에 따라 두 번 또는 한 번에 'X'를 인쇄 할 명령을 -n옵션.


좋은 댓글을 올리려면 +1 댓글이없는 프로그램이 너무 많습니다.
David Cary

4

여기에 sed모든 라인을 sed"홀드 스페이스" 로 연결하는 또 다른 솔루션이 있습니다. 따라서 패턴 일치를 위해 하나의 긴 문자열을 "패턴 스페이스"에 복사합니다.

sed'패턴 공간'의 마지막 긴 문자열에서 줄 바꿈이 유지되므로 이중 줄 바꿈과 관련하여 빈 줄을 [^\n]\n\n[^\n]일치시키고 수정할 수 있습니다.[^\n]\n[^\n] .

자세한 정보는 예를 들어 sed 및 복수 라인 검색 및 바꾸기를 참조하십시오 .

text='
line 1

line 2
line 3





line 4


line     5



line 6
line 7

line 8
'

# FreeBSD sed
# first sed deletes first / last line if empty and squeezes multiple spaces
printf '%s' "$text" |
sed -e '1{/^$/d;}' -e '${/^$/d;}' -e '/[[:space:]]\{2,\}/s// /g' | 
sed -n -e '1h;1!H;${;g;/\([^[:cntrl:]]\)\n\n\([^[:cntrl:]]\)/s//\1\
\2/g;p;}' |
nl -b a


# GNU sed
# alternative using ...;x;... instead of ...;g;...
# cf. man sed | less -p '\]x'
printf '%s' "$text" |
gsed -e '1{/^$/d;}' -e '${/^$/d;}' -e '/[[:space:]]\{2,\}/s// /g' | 
gsed -E -n '1h;1!H;${;x;/([^\n])\n\n([^\n])/s//\1\
\2/g;p;}' | 
nl -b a


# remove all the single linebreaks but leave the double linebreaks intact
printf '%s' "$text" | 
   sed -n -e '1h;1!H;${;g;/\([^[:cntrl:]]\)\n\([^[:cntrl:]]\)/s//\1 \2/g;p;}' | 
   nl -b a

3

이것은 오래된 학교 일 수 있습니다.

(echo ".pl 1" ; echo ".ll 80" ; echo ".ad l" ; cat your_file) | nroff

.ad l줄 길이가 80 ( .ll 80) 인 텍스트를 왼쪽 정렬 ( )로 출력합니다 . 페이지 길이 옵션 ( .pl)은 텍스트 처리기에 페이지 길이가 1 인 페이지 패딩을 수행하도록 지시하므로 페이지 패딩은 없습니다.

모든 단락을 한 줄에 표시하려면 다음에 큰 숫자를 사용할 수 있습니다 .ll.

(echo ".pl 1" ; echo ".ll 1000000" ; echo ".ad l" ; cat your_file) | nroff

더 많은 서식 옵션에 대해서는 man 7 groff .


1

이맥스에서 나는 때때로 이것을 사용한다 regex:

^J\([^^J]\) -> \1

방법:

줄 바꿈이 아닌 모든 줄 바꿈을 바꾸고 줄 바꿈을 따르는 것입니다. 그런 식으로 단락 내의 모든 줄 바꿈을 제거하지만 단락을 유지합니다 (이중 줄 바꿈)


0

그것은으로 밝혀 auto-fill-mode에, 이맥스는 단지 내 간단한 사용 사례에 대한 꽤 좋은 일을 M-q...


auto-fill-mode어떤 주요 모드가 활성화되어 있는지에 대한 세부 사항 이 다릅니다.
dmckee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.