etc./StackOverFlow

sed를 사용하여 줄 바꿈(\n)을 어떻게 바꿀 수 있습니까?

청렴결백한 만능 재주꾼 2022. 2. 19. 05:49
반응형

질문자 :hhh


줄 바꿈(" \n ")을 공백(" ") sed 명령을 사용하고 있습니까?

나는 실패했다:

 sed 's#\n# #g' file sed 's#^$# #g' file

어떻게 수정합니까?



sed 는 라인 기반 입력에 사용하기 위한 것입니다. 그것이 당신이 필요로하는 것을 할 수 있지만.


더 나은 옵션은 다음과 같이 tr

 tr '\n' ' ' < input_filename

또는 개행 문자를 완전히 제거하십시오.

 tr -d '\n' < input.txt > output.txt

또는 GNU 버전이 있는 경우(긴 옵션 포함)

 tr --delete '\n' < input.txt > output.txt

dmckee --- ex-moderator kitten

이 솔루션을 GNU sed 와 함께 사용하십시오.

 sed ':a;N;$!ba;s/\n/ /g' file

이것은 루프에서 전체 파일을 읽은 다음 줄 바꿈을 공백으로 바꿉니다.

설명:

  1. :a 를 통해 레이블을 만듭니다.
  2. N 통해 패턴 공간에 현재 행과 다음 행을 추가합니다.
  3. 마지막 줄 앞에 있으면 생성된 레이블 $!ba 분기합니다( $! 는 마지막 줄 바꿈이 하나 있어야 하므로 마지막 줄에서 수행하지 않음을 의미합니다).
  4. 마지막으로 대체는 모든 개행을 패턴 공간(전체 파일)의 공백으로 대체합니다.

sed 와 함께 작동하는 플랫폼 간 호환 구문입니다( @Benjie 주석에 따름 ).

 sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file

보시다시피 sed 를 사용하는 것은 문제가 됩니다. 더 간단하고 적절한 솔루션은 이 답변을 참조하십시오.


Zsolt Botykai

빠른 답변

 sed ':a;N;$!ba;s/\n/ /g' file
  1. :a 레이블 'a' 생성
  2. N 패턴 공간에 다음 줄 추가
  3. $! 마지막 줄이 아닌 경우 ba 분기(이동) 레이블 'a'
  4. s 대체 , /\n/ 새 줄에 대한 정규식 , / / 공백으로 , /g 전역 일치(가능한 한 많이)

sed는 마지막 줄에 도달할 때까지 1~3단계를 반복하여 sed가 모든 \n 문자를 대체하는 패턴 공간에 모든 줄을 맞춥니다.


대안

sed 와 달리 모든 대안은 프로세스를 시작하기 위해 마지막 줄에 도달할 필요가 없습니다.

bash 로 천천히

 while read line; do printf "%s" "$line "; done < file

perl , sed 같은 속도

 perl -p -e 's/\n/ /' file

tr을 사용 하면 sed 보다 빠르며 한 문자로만 바꿀 수 있습니다.

 tr '\n' ' ' < file

paste , tr 같은 속도로 한 문자로만 대체 가능

 paste -s -d ' ' file

awk , tr 같은 속도로

 awk 1 ORS=' ' file

"echo $(< file)" 과 같은 다른 대안은 느리고 작은 파일에서만 작동하며 프로세스를 시작하려면 전체 파일을 처리해야 합니다.


sed FAQ 5.10 의 긴 답변

5.10. \n 이스케이프를 사용하여 개행을 일치시키거나 삭제할 수 없는 이유
순서? \n을 사용하여 2개 이상의 라인을 일치시킬 수 없는 이유는 무엇입니까?

\n은 줄 끝에서 줄 바꿈과 일치하지 않습니다. 왜냐하면
줄 바꿈은 줄을 삽입하기 전에 항상 제거됩니다.
패턴 공간. 패턴 공간에 2개 이상의 라인을 가져오려면 다음을 사용하십시오.
'N' 명령 또는 이와 유사한 것(예: 'H;...;g;').

Sed는 다음과 같이 작동합니다. sed는 한 번에 한 줄씩 읽고 잘라냅니다.
줄 바꿈을 종료하고 남은 것을 패턴 공간에 넣습니다.
sed 스크립트는 주소를 지정하거나 변경할 수 있으며 패턴 공간이
인쇄되면 stdout(또는 파일)에 개행을 추가합니다. 만약
패턴 공간이 'd' 또는 'D'로 완전히 또는 부분적으로 삭제되고,
이러한 경우 줄 바꿈이 추가되지 않습니다. 따라서 다음과 같은 스크립트

 sed 's/\n//' file # to delete newlines from each line sed 's/\n/foo\n/' file # to add a word to the end of each line

후행 줄 바꿈이 전에 제거되기 때문에 작동하지 않습니다.
선은 패턴 공간에 놓입니다. 위의 작업을 수행하려면
대신 다음 스크립트 중 하나를 사용하십시오.

 tr -d '\n' < file # use tr to delete newlines sed ':a;N;$!ba;s/\n//g' file # GNU sed to delete newlines sed 's/$/ foo/' file # add "foo" to end of each line

GNU sed 이외의 sed 버전에는 크기에 제한이 있기 때문에
패턴 버퍼, Unix 'tr' 유틸리티가 여기에서 선호됩니다.
파일의 마지막 줄에 줄 바꿈이 포함되어 있으면 GNU sed는 다음을 추가합니다.
그 개행을 출력에 추가하지만 나머지는 모두 삭제하는 반면 tr은
모든 개행을 삭제하십시오.

두 개 이상의 라인 블록을 일치시키려면 3가지 기본 선택 사항이 있습니다.
(1) 'N' 명령을 사용하여 패턴 공간에 다음 줄을 추가합니다.
(2) 'H' 명령을 두 번 이상 사용하여 현재 줄을 추가합니다.
보류 공간으로 이동한 다음 보류 공간에서 라인을 검색합니다.
x, g 또는 G와 함께; 또는 (3) 주소 범위 사용(위의 섹션 3.3 참조)
두 개의 지정된 주소 사이의 행을 일치시킵니다.

선택 사항 (1)과 (2)는 \n을 패턴 공간에 넣습니다.
원하는 대로 주소를 지정할 수 있습니다('s/ABC\nXYZ/alphabet/g'). 한 가지 예
라인 블록을 삭제하기 위해 'N'을 사용하는 방법은 섹션 4.13에 나와 있습니다.
("특정 연속 라인 블록을 어떻게 삭제합니까?"). 이것
삭제 명령을 무언가로 변경하여 예제를 수정할 수 있습니다.
그렇지 않으면 'p'(인쇄), 'i'(삽입), 'c'(변경), 'a'(추가),
또는 ''(대체).

선택 (3)은 \n을 패턴 공간에 넣지 않지만
연속 행 블록과 일치하므로 일치하지 않을 수 있습니다.
찾고 있는 것을 찾으려면 \n도 필요합니다. GNU sed 이후로
버전 3.02.80은 이제 다음 구문을 지원합니다.

 sed '/start/,+4d' # to delete "start" plus the next 4 lines,

기존의 '/여기에서/,/까지/{...}' 범위 외에
주소를 사용하면 \n 사용을 완전히 피할 수 있습니다.


hdorio

더 짧은 awk 대안:

 awk 1 ORS=' '

설명

awk 프로그램은 조건부 코드 블록으로 구성된 규칙으로 구성됩니다. 예:

 condition { code-block }

코드 블록이 생략되면 기본값이 사용됩니다. { print $0 } . 따라서 1 은 참 조건으로 해석되고 각 행에 대해 print $0

awk 가 입력을 읽을 때 RS (Record Separator) 값을 기반으로 레코드로 분할합니다. awk 는 기본적으로 입력을 라인 단위로 구문 분석합니다. 분할에는 입력 레코드에서 RS 를 제거하는 것도 포함됩니다.

이제 레코드를 인쇄할 때 ORS (Output Record Separator)가 추가되고 기본값은 다시 개행입니다. 따라서 ORS 를 공백으로 변경하면 모든 줄 바꿈이 공백으로 변경됩니다.


Thor

GNU sed에는 널로 구분된 레코드(줄)에 대해 -z 다음과 같이 전화하면 됩니다.

 sed -z 's/\n/ /g'

JJoao

Perl 버전은 예상대로 작동합니다.

 perl -i -p -e 's/\n//' file

주석에서 지적했듯이 이 편집이 제자리에 있다는 점은 주목할 가치가 있습니다. -i.bak 은 정규식 이 생각만큼 똑똑하지 않은 경우 대체하기 전에 원본 파일의 백업을 제공합니다.


ire_and_curses

sed 가 필요합니까? 다음은 bash 방식입니다.

 cat test.txt | while read line; do echo -n "$line "; done

commonpike

전체 파일을 메모리로 읽지 않고 awk를 사용하여 모든 개행을 공백으로 바꾸려면 다음을 수행하십시오.

 awk '{printf "%s ", $0}' inputfile

마지막 줄 바꿈을 원하면 다음을 수행하십시오.

 awk '{printf "%s ", $0} END {printf "\n"}' inputfile

공백 이외의 문자를 사용할 수 있습니다.

 awk '{printf "%s|", $0} END {printf "\n"}' inputfile

Dennis Williamson

tr '\n' ' '

명령입니다.

간단하고 사용하기 쉽습니다.


Dheeraj R

세개.

  1. tr (또는 cat 등)은 절대 필요하지 않습니다. (GNU) sed 및 (GNU) awk 를 결합하면 필요한 모든 텍스트 처리의 99.9%를 수행할 수 있습니다.

  2. 스트림 != 라인 기반. ed 는 라인 기반 편집기입니다. sed 는 아닙니다. 차이점에 대한 자세한 내용 은 sed 강의 를 참조하십시오. 대부분의 사람들은 sed 가 기본적으로 SIMPLE 일치에 대한 패턴 일치에 그다지 욕심이 없기 때문에 라인 기반으로 혼동합니다. 예를 들어 패턴 검색을 수행하고 한두 문자로 바꿀 때 기본적으로 첫 번째 문자만 대체합니다 찾은 것과 일치합니다(전역 명령에서 달리 지정하지 않는 한). STREAM 기반이 아니라 라인 기반이라면 한 번에 라인만 평가하기 때문에 전역 명령도 존재하지 않습니다. ed 실행해 보십시오. 당신은 차이를 알 수 있습니다. ed 는 특정 행(for 루프에서와 같이)을 반복하려는 경우에 매우 유용하지만 대부분의 경우 sed 만 원할 것입니다.

  3. 말하자면,

     sed -e '{:q;N;s/\n/ /g;tq}' file

    sed 버전 4.2.1에서 잘 작동합니다. 위의 명령은 모든 줄 바꿈을 공백으로 바꿉니다. 입력하는 것이 추하고 약간 번거롭지만 잘 작동합니다. {} 는 정상적인 이유로만 포함되므로 생략할 수 있습니다.


brent saner

이해하기 쉬운 솔루션

나는이 문제가 있었다. 중요한 것은 BSD(Mac OS X) 및 GNU(Linux 및 Cygwin ) sedtr 에서 작동하는 솔루션이 필요하다는 것이었습니다.

 $ echo 'foo bar baz foo2 bar2 baz2' \ | tr '\n' '\000' \ | sed 's:\x00\x00.*:\n:g' \ | tr '\000' '\n'

산출:

 foo bar baz

(뒤에 줄 바꿈이 있음)

Linux, OS X 및 BSD에서 작동합니다. UTF-8 지원이 없거나 형편없는 터미널이 있어도 마찬가지입니다.

  1. tr 을 사용하여 줄 바꿈을 다른 문자로 바꿉니다.

    NULL ( \000 또는 \x00 )은 UTF-8 지원이 필요하지 않고 사용되지 않을 가능성이 높기 때문에 좋습니다.

  2. sed 를 사용 NULL

  3. tr 을 사용하여 추가 줄 바꿈을 다시 교체하십시오.


coolaj86

:a 레이블이 있는 답은 ...

sed를 사용하여 줄 바꿈(\n)을 어떻게 바꿀 수 있습니까?

... 명령줄의 freebsd 7.2에서는 작동하지 않습니다.

( 에코 foo ; 에코 바 ) | sed ':a;N;$!ba;s/\n/ /g'
sed: 1: ":a;N;$!ba;s/\n/ /g": 사용되지 않은 레이블 'a;N;$!ba;s/\n/ /g'
푸
술집

그러나 sed 스크립트를 파일에 넣거나 -e를 사용하여 sed 스크립트를 "빌드"하면 ...

> (에코 푸, 에코 바) | sed -e :a -e N -e '$!ba' -e 's/\n/ /g'
푸 바

또는 ...

 > cat > x.sed << eof :a N $!ba s/\n/ /g eof > (echo foo; echo bar) | sed -f x.sed foo bar

아마도 OS X의 sed도 비슷할 것입니다.


Juan

xargs 를 사용할 수 있습니다.

 seq 10 | xargs

또는

 seq 10 | xargs echo -n

Vytenis Bivainis

awk 로 간단한 해결책을 찾지 못한 이유는 무엇입니까?

 awk '{printf $0}' file

원래 줄을 공백이나 기타로 구분하려는 경우 printf

 awk '{printf $0 " "}' file

Itachi

불행히도 Windows 줄 끝을 처리해야 하는 경우 \r\n 을 제거해야 합니다.

 tr '\r\n' ' ' < $input > $output

StevenWernerCS

저는 전문가는 아니지만 sed N "을 사용하여 bij 패턴 공간에 다음 줄을 추가해야 할 것 같습니다. 책 sed & awk (Dale Dougherty and Arnold Robbins, O'Reilly 1997, 미리보기 107페이지)의 "고급 sed 명령"에 있는 "다중 줄 패턴 공간" 섹션에서:

multiline Next(N) 명령은 새 입력 줄을 읽고 패턴 공간의 내용에 추가하여 여러 줄 패턴 공간을 만듭니다. 패턴 공간의 원래 내용과 새 입력 행은 개행으로 구분됩니다. 포함된 개행 문자는 이스케이프 시퀀스 "\n"에 의해 패턴에서 일치될 수 있습니다. 여러 줄 패턴 공간에서 메타 문자 "^"는 패턴 공간의 맨 처음 문자와 일치하며 포함된 줄 바꿈 다음에 오는 문자는 일치하지 않습니다. 마찬가지로 "$"는 패턴 공간의 마지막 줄 바꿈에만 일치하며 포함된 줄 바꿈은 일치하지 않습니다. 다음 명령이 실행된 후 제어는 스크립트의 후속 명령으로 전달됩니다.

man sed :

[2addr]N

삽입된 개행 문자를 사용하여 추가된 자료를 원본 내용과 분리하여 패턴 공간에 입력의 다음 줄을 추가합니다. 현재 줄 번호가 변경됩니다.

나는 이것을 (여러 개의) 잘못된 형식의 로그 파일을 검색하는 데 사용 했으며 검색 문자열은 "고아" 다음 줄에서 찾을 수 있습니다.


Arjan

위의 "tr" 솔루션에 대한 응답으로 Windows(아마도 Gnuwin32 버전의 tr 사용)에서 제안된 솔루션은 다음과 같습니다.

 tr '\n' ' ' < input

나를 위해 작동하지 않았다, 그것은 오류가 발생하거나 실제로 어떤 이유로 \nw/ ''를 대체합니다.

tr의 또 다른 기능을 사용하여 "삭제" 옵션 -d가 작동했습니다.

 tr -d '\n' < input

또는 '\n' 대신 '\r\n'


John Lawler

하이브리드 접근 방식을 사용하여 tr을 사용하여 개행을 탭으로 대체한 다음 탭을 원하는 것으로 대체함으로써 개행 문제를 해결했습니다. 이 경우 "
" HTML 나누기를 생성하려고 하기 때문에.

 echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`

rfengr

방탄 솔루션. 바이너리 데이터에 안전하고 POSIX와 호환되지만 느립니다.

POSIX sed 는 POSIX 텍스트 파일POSIX 행 정의에 따라 입력이 필요하므로 NULL 바이트 및 너무 긴 행은 허용되지 않으며 각 행은 개행(마지막 행 포함)으로 끝나야 합니다. 이것은 임의의 입력 데이터를 처리하기 위해 sed를 사용하기 어렵게 만듭니다.

다음 솔루션은 sed를 피하고 대신 입력 바이트를 8진수 코드로 변환한 다음 다시 바이트열로 변환하지만 8진수 코드 012(개행)를 가로채 그 자리에 대체 문자열을 출력합니다. 내가 말할 수 있는 한 솔루션은 POSIX와 호환되므로 다양한 플랫폼에서 작동해야 합니다.

 od -A n -t o1 -v | tr ' \t' '\n\n' | grep . | while read x; do [ "0$x" -eq 012 ] && printf '<br>\n' || printf "\\$x"; done

POSIX 참조 문서: sh ,쉘 명령 언어 , od , tr , grep , read , [ , printf .

read , [ , printf 둘 다 최소한 bash에서는 내장되어 있지만 POSIX에서는 보장하지 않을 수 있으므로 일부 플랫폼에서는 각 입력 바이트가 하나 이상의 새 프로세스를 시작하여 속도가 느려질 수 있습니다. bash에서도 이 솔루션은 약 50kB/s에 도달하므로 대용량 파일에는 적합하지 않습니다.

Ubuntu(bash, dash 및 busybox), FreeBSD 및 OpenBSD에서 테스트되었습니다.


Håkon A. Hjortland

어떤 상황에서는 RS 를 다른 문자열이나 문자로 변경할 수 있습니다. 이렇게 하면 \n을 sub/gsub에 사용할 수 있습니다.

 $ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print $0 }' file

쉘 스크립팅의 장점은 한 가지 방법으로 수행하는 방법을 모르는 경우 다른 방법으로 수행할 수 있다는 것입니다. 그리고 많은 경우에는 단순한 문제에 대해 복잡한 솔루션을 만드는 것보다 고려해야 할 사항이 더 많습니다.

gawk가 느리고 파일을 메모리로 읽는 것과 관련하여, 나는 이것을 알지 못하지만, 나에게 gawk는 한 번에 한 줄로 작동하는 것으로 보이며 매우 매우 빠릅니다(다른 것들만큼 빠르지는 않습니다) 하지만 작성하고 테스트하는 시간도 중요합니다).

나는 MB 및 GB의 데이터를 처리하고 내가 찾은 유일한 한계는 라인 크기입니다.


mor

허용 \n을 사용하여 찾기 및 바꾸기

 sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt

채점자

된다

# 마커 코멘트

채점자


Proximo

이 방법을 사용할 수도 있습니다.

 sed 'x;G;1!h;s/\n/ /g;$!d'

설명

 x - which is used to exchange the data from both space (pattern and hold). G - which is used to append the data from hold space to pattern space. h - which is used to copy the pattern space to hold space. 1!h - During first line won't copy pattern space to hold space due to \n is available in pattern space. $!d - Clear the pattern space every time before getting the next line until the the last line.

흐름

첫 번째 줄이 입력에서 가져오면 교환이 이루어지므로 1 은 유지 공간으로 이동하고 \n 은 패턴 공간으로 이동하여 패턴 공간에 유지 공간을 추가하고 대체가 수행되고 패턴 공간이 삭제됩니다.

두 번째 줄에서 교환이 이루어지고 2 는 유지 공간으로 이동하고 1 은 패턴 공간으로 이동하고 G 는 유지 공간을 패턴 공간에 추가하고 h 는 패턴을 복사하고 대체가 이루어지고 삭제됩니다. 이 작업은 EOF에 도달하고 정확한 결과를 인쇄할 때까지 계속됩니다.


Kalanidhi

xargs 사용할 수 있습니다 — \n 을 공백으로 바꿉니다.

unterminated quote 이 있는 경우(예: 주어진 줄의 인용 부호가 일치하지 않는 경우) 문제가 발생합니다.


cnst

Mac OS X(FreeBSD sed 사용):

 # replace each newline with a space printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta' printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta

bashfu

빈 줄을 제거하려면:

 sed -n "s/^$//;t;p;"

kralyk

awk 사용:

 awk "BEGIN { o=\"\" } { o=o \" \" \$0 } END { print o; }"

kralyk

내가 특히 좋아하는 솔루션은 모든 파일을 보류 공간에 추가하고 파일 끝에 있는 모든 개행 문자를 교체하는 것입니다.

 $ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}' foobar

그러나 누군가는 일부 sed 구현에서 보류 공간이 유한할 수 있다고 말했습니다.


brandizzi

줄 바꿈을 문자열로 바꾸고 마지막 줄 바꿈도 교체하십시오.

순수 tr 솔루션은 단일 문자로만 대체할 수 있으며 순수 sed 솔루션은 입력의 마지막 줄 바꿈을 대체하지 않습니다. 다음 솔루션은 이러한 문제를 해결하고 바이너리 데이터(UTF-8 로케일을 사용하는 경우에도)에 안전한 것으로 보입니다.

 printf '1\n2\n3\n' | sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'

결과:

 1<br>2<br>3<br>

Håkon A. Hjortland

"정상"대체 후 개행 을 도입하는 것은 sed입니다. 먼저 줄 바꿈 문자를 트리밍한 다음 지침에 따라 처리한 다음 줄 바꿈을 도입합니다.

sed 를 사용하면 잘린 후 줄의 "끝"(개행 문자 아님)을 각 입력 줄에 대해 선택한 문자열로 바꿀 수 있습니다. 그러나 sed 는 다른 행을 출력합니다. 예를 들어 "줄 끝"을 "==="(단일 공백으로 바꾸는 것보다 더 일반적임)으로 바꾸고 싶다고 가정합니다.

 PROMPT~$ cat <<EOF |sed 's/$/===/g' first line second line 3rd line EOF first line=== second line=== 3rd line=== PROMPT~$

개행 문자를 문자열로 바꾸려면 비효율적 으로 앞에서 지적한 대로 tr 을 사용하여 개행 문자를 "특수 문자" 로 대체한 다음 sed 를 사용하여 해당 특수 문자를 원하는 문자열로 대체할 수 있습니다. .

예를 들어:

 PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g' first line second line 3rd line EOF first line===second line===3rd line===PROMPT~$

Robert Vila

Zsolt Botykai 의 답변 과 거의 동일한 또 다른 GNU sed 방법이지만 이것은 sed 의 덜 자주 사용되는 y ( 음역 ) 명령을 사용하여 1바이트 의 코드(후행 g )를 저장합니다.

 sed ':a;N;$!ba;y/\n/ /'

누군가는 y s 보다 빠르게 실행되기를 희망하지만( tr 속도에서 20배 더 빠름) GNU sed v4.2.2에서 ys 보다 약 4% 느립니다.


더 휴대용 BSD sed 버전:

 sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'

agc

출처 : http:www.stackoverflow.com/questions/1251999/how-can-i-replace-a-newline-n-using-sed

반응형