패턴 앞에 줄 바꿈을 삽입하는 방법은 무엇입니까?


138

줄 내에서 패턴 앞에 줄 바꿈을 삽입하는 방법은 무엇입니까?

예를 들어 정규식 패턴 뒤에 줄 바꿈을 삽입합니다 .

sed 's/regex/&\n/g'

패턴 앞에서 똑같이 어떻게 할 수 있습니까?

이 샘플 입력 파일이 있으면 일치하는 패턴이 전화 번호입니다.

some text (012)345-6789

되어야한다

some text
(012)345-6789


1
@NilsvonBarth, 왜 간단한 질문이 나쁜 질문입니까?
Josh

답변:


177

이것은 작동 bash하고 zsh리눅스와 OS X에서 테스트 :

sed 's/regexp/\'$'\n/g'

일반적으로 $작은 따옴표로 묶인 문자열 리터럴 bash은 C 스타일 백 슬래시 대체를 수행합니다 (예 : $'\t'리터럴 탭으로 변환). 또한 sed는 개행 문자를 백 슬래시로 이스케이프 처리하기를 원하므로 \이전 $. 마지막으로 달러 기호 자체는 셸에서 해석되도록 따옴표로 묶지 않아야하므로 따옴표 앞에 따옴표 $를 닫았다가 다시여십시오.

편집 : @ mklement0의 의견에서 제안했듯이 다음과 같이 작동합니다.

sed $'s/regexp/\\\n/g'

여기서 일어나는 일은 : 전체 sed 명령은 이제 C 스타일 문자열입니다. 이는 새 줄 리터럴이 다른 백 슬래시로 이스케이프되기 전에 sed가 배치되어야하는 백 슬래시를 의미합니다. 더 읽기 쉽지만이 경우 셸 문자열 대체를 수행 할 수 없습니다 (다시 작성하지 않아도 됨).


7
이것은 OSX에서 "대체 패턴 안에 이스케이프 처리되지 않은 줄 바꿈"을 제공합니다.
매트 깁슨

대체 패턴 내에 백 슬래시가없는 실제 줄 바꿈이있는 경우에만 "이스케이프되지 않은 줄 바꿈"이 제공되므로 @Matt Gibson은 매우 이상합니다. 위의 코드는 사실 zsh, ksh와 같은 다른 쉘에서도 작동합니다.
mojuba

3
@Matt Gibson ... 또는 내 코드에서 '$'\ n 앞의 백 슬래시를 잊어 버린 경우.
mojuba

7
작성된 바와 같이, 이러한 표현식은 요청에 따라 기존 행의 중간에 개행을 삽입하는 대신 정규식을 개행으로 완전히 대체합니다. 다음은이 답변의 수정 된 형식을 사용하여 두 개의 일치 패턴 사이에 개행을 삽입하는 방법 sed '\(first match\)\(second match\)/\1\'$'\n''\2/g'입니다. \ n 뒤에 두 개의 작은 따옴표가 있습니다. 첫 번째 $줄은 " "섹션을 닫아서 나머지 줄이 영향을받지 않도록합니다. 인용 부호가 없으면 \ 2는 무시되었습니다.
David Ravetti

12
또 다른 옵션은 사용하는 단일 ANSI C-인용 된 문자열 : sed $'s/regexp/\\\n/g'가독성을 향상 - 유일한주의해야 할 점은 당신이 다음 필요가있다 두배로 모든 리터럴 \ 문자를.
mklement0

43

다른 답변 중 일부가 내 버전의 sed에서 작동하지 않았습니다. 의 위치를 전환 &하고하는 \n일을했다.

sed 's/regexp/\n&/g' 

편집 : 설치하지 않으면 OS X에서 작동하지 않는 것 같습니다 gnu-sed.


9
이것이 모든 버전의 sed에서 작동하는지 확실하지 않습니다. Mac에서이 작업을 시도했는데 \ n은 'n'으로 출력됩니다.
Todd Gamblin

3
대답을 읽기 전에 직장에서 맥에서 15 분을 보냈다. 애플로가요!
Rick77

1
사제를 사용하는 경우 : brew install gnu-sed다음gsed 's/regexp/\n&/g'
AAAAAA

1
... 다음에echo 'alias sed=gsed' >> ~/.bashrc
Proximo

36

sed에서는 출력 스트림에 개행을 쉽게 추가 할 수 없습니다. 어색한 연속 줄을 사용해야하지만 다음과 같이 작동합니다.

$ sed 's/regexp/\
&/'

예:

$ echo foo | sed 's/.*/\
&/'

foo

자세한 내용은 여기 를 참조 하십시오 . 조금 덜 어색한 것을 원한다면 perl -pesed 대신 match 그룹을 사용해보십시오 .

$ echo foo | perl -pe 's/(.*)/\n$1/'

foo

$1 그룹이 괄호 안에있는 정규식에서 첫 번째 일치 그룹을 나타냅니다.


개행을 추가 할 수없는 이유는 무엇입니까? 당신은 sed 's / regexp / & \ n / g'를 할 수 있습니다. 그것이
끝났

2
이것은 줄 바꿈을 삽입하기 위해 Mac에서 할 수있는 가장
해킹적인

펄 버전은 제자리 편집을 위해 수정 될 수 있습니다perl -pi -e 's/(.*)/\n$1/' foo
Eponymous

2
@Andres : (대부분) OS X와 ​​함께 제공되는 BSD 버전과 같은 POSIX 기능 전용 Sed 구현은 s함수 호출 의 대체 부분에서 제어 문자 이스케이프 시퀀스를 지원하지 않습니다 ( GNU Sed 구현 과 달리 ) . 위의 답변은 두 가지 구현 모두에서 작동합니다. 모든 차이점에 대한 개요는 여기를 참조 하십시오 .
mklement0

29

내 Mac에서 다음은 줄 바꿈 대신 단일 'n'을 삽입합니다.

sed 's/regexp/\n&/g'

이것은 개행으로 대체됩니다.

sed "s/regexp/\\`echo -e '\n\r'`/g"

인라인 편집을 sed -i '' -e ...하고 ^M캐럿 M (Ctrl + m)이 파일에 기록되는 데 문제가있었습니다 . 나는 같은 매개 변수로 펄을 사용했다.
Steve Tauber

2
두 번째 코드는 특수 줄 바꿈 코드 LF CR (MS-DOS CR LF와 반대)을 삽입한다는 사실에 유의하십시오! 유닉스 계열 OS와 Mac OS X 모두 LF ( \n) 만 사용 합니다.
pabouk

내 sed 표현에서 다른 것이 너무 행복하지 않아서 ( echo...그리고 개행 없이 잘 작동하더라도 ) vim에서 방금 수행했습니다.
Ahmed Fasih

1
또는 간단히 : sed "s/regexp/`echo`/g"
-LF

2
@mojuba : 아니오 : `echo`가 발생합니다 빈 문자열 명령 대체는 예외없이 모든 후행 뉴 라인 트림 때문에. 명령 대체를 사용하여 단일 개행을 직접 삽입 할 수있는 방법이 없습니다 ( \n\r추가 CR을 삽입 하는 것은 끔찍한 생각입니다).
mklement0

15
echo one,two,three | sed 's/,/\
/g'

1
+1 완벽하고 꽤 stright-forward / remember-to-
member 히

2
이 답변은 실제로 bash 솔루션이 아닌 sed 솔루션입니다. 구문을 사용 하는 것은 쉘을 사용하여 개행을 생성하는 것입니다. 이러한 솔루션은 이식성이 없을 수 있습니다. 이것입니다. 물론, 이것은 2009 년 tgamblin의 답변에서 두 번째 예의 복제본이기도합니다.$'\n'
ghoti

10

이 경우에는 sed를 사용하지 않습니다. 나는 tr을 사용한다.

cat Somefile |tr ',' '\012' 

쉼표를 사용하여 캐리지 리턴으로 바꿉니다.


1
:이 또한 작동 발견 cat Somefile | tr ',' '\n'YMMV
LS

9

완전한 펄 정규 표현식 지원 (sed로 얻는 것보다 훨씬 강력 함) 의 장점으로 sed에서와 마찬가지로 perl one-liner를 사용할 수 있습니다 . * nix 플랫폼 간에는 변형이 거의 없습니다. perl은 일반적으로 perl입니다. 따라서 특정 시스템의 sed 버전을 원하는 방식으로 수행하는 방법에 대해 걱정하지 않아도됩니다.

이 경우에는 할 수 있습니다

perl -pe 's/(regex)/\n$1/'

-pe sed의 정상 작동 모드와 매우 유사하게 펄을 "실행 및 인쇄"루프에 넣습니다.

' 쉘이 방해하지 않도록 다른 모든 것을 인용

()정규 표현식을 둘러싼 그룹화 연산자입니다. $1대치의 오른쪽에이 parens에 일치하는 것이 인쇄됩니다.

마지막으로 \n줄 바꿈입니다.

괄호를 그룹화 연산자로 사용하는지 여부에 관계없이 일치시키려는 괄호를 피해야합니다. 따라서 위에 나열된 패턴과 일치하는 정규식은 다음과 같습니다.

\(\d\d\d\)\d\d\d-\d\d\d\d

\(또는 \)리터럴 패런과 \d일치하고 숫자 와 일치합니다.

보다 나은:

\(\d{3}\)\d{3}-\d{4}

나는 중괄호 안의 숫자가 무엇을하는지 알아낼 수 있다고 생각합니다.

또한 정규 표현식에 / 이외의 구분 기호를 사용할 수 있습니다. 따라서 일치 해야하는 경우 / 탈출 할 필요가 없습니다. 아래 중 하나는 내 대답의 시작 부분에있는 정규식과 같습니다. 이론적으로 당신은 표준 /의 문자 를 대체 할 수 있습니다 .

perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'

몇 가지 최종 생각.

사용은 -ne대신 -pe유사하게 작용하지만, 자동으로 마지막에 인쇄되지 않습니다. 직접 인쇄하려는 경우 편리 할 수 ​​있습니다. 예를 들어, 여기 grep-alike가 있습니다 ( m/foobar/정규식 일치).

perl -ne 'if (m/foobar/) {print}'

줄 바꿈 문제를 다루는 것을 발견하고 마술처럼 다루기를 원한다면을 추가하십시오 -l. 그러나 개행 작업을 한 OP에게는 유용하지 않습니다.

보너스 팁-pcre 패키지가 설치되어 있으면 pcregrep전체 perl 호환 정규식을 사용 하는이 함께 제공됩니다 .


4

흠, 방금 줄 바꿈 줄은 최신 버전 sed(GNU sed 4.2.1이 있음) 에서 작동하는 것처럼 보입니다 .

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar

1
언급했듯이 이것은 다양한 버전의 GNU sed에서 작동하지만 macOS에 포함 된 sed에서는 작동하지 않습니다.
LS

4
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

El Captitan에서 잘 ()지원했습니다.


이것은 훌륭하게 작동했으며 자신의 목적을 위해 전문화하기 위해 테스트하고 외삽하는 완전한 명령을 내릴 수도 있습니다. 좋은 작업!
jxramos

3

리눅스에서 출력 스트림에 개행을 삽입하려면 다음을 사용했습니다.

sed -i "s/def/abc\\\ndef/" file1

어디에 file1있었 습니까 ?

def

sed 전체 교체 전, 그리고 :

abc
def

sed 전체 교체 후. 의 사용에 유의하십시오 \\\n. "내부에 패턴이 있으면를 사용하여 이스케이프 처리하십시오 \".


나에게 위의 코드는 작동하지 않습니다. 쉘에서 매개 변수를 가져 오기 때문에 LF 대신 sed삽입 \n합니다 \\n. ---이 코드는 작동합니다 sed -i "s/def/abc\ndef/" file1. --- GNU sed version 4.2.1, GNU bash, version 4.1.2(1) / 4.2.25(1)(CentOS 릴리스 6.4 / Ubuntu 12.04.3).
pabouk

2

sed에서는 "\ 1", "\ 2"등으로 패턴의 그룹을 참조 할 수 있습니다. 따라서 찾고있는 패턴이 "PATTERN"이고 그 앞에 "BEFORE"를 삽입하려는 경우 , 당신은 산세 탈출을 사용할 수 있습니다

sed 's/(PATTERN)/BEFORE\1/g'

  sed 's/\(PATTERN\)/BEFORE\1/g'

방금 테스트 한 내용 : testfile contents = "ABC ABC ABC". "sed 's / \ (ABC \) / \ n \ 1 / g'테스트 파일을 실행했습니다. 줄 바꿈을 얻었습니다. 이스케이프를 실험하고 패턴에 한 번에 한 가지만 추가하십시오. 예를 들어 패턴, 그룹 일치를 확인한 다음 줄 바꿈 검사를 추가합니다
Steve B.

난 그냥 정확히 시도하고 "nABC nABC nABC"를 얻었다. 다른 버전의 sed를 사용하고 있습니까?
Todd Gamblin

쉘 탈출은 아마도 tgamblin의 시도를 방해하고 있습니다. Steve B와 같이 전체 sed 인수를 작은 따옴표로 묶으면 문제가 해결됩니다. sed의 다른 버전이 줄 바꿈에 대한 \ n을 이해하지 못하더라도 가능합니다.
Dan Pritts

2

-v패턴을 제공하기 위해 awk를 사용하여이 작업을 수행 할 수도 있습니다 .

awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file

라인에 주어진 패턴이 포함되어 있는지 확인합니다. 그렇다면 시작 부분에 새 줄을 추가합니다.

기본 예를 참조하십시오.

$ cat file
hello
this is some pattern and we are going ahead
bye!
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
hello
this is some 
pattern and we are going ahead
bye!

한 줄의 모든 패턴에 영향을 미칩니다.

$ cat file
this pattern is some pattern and we are going ahead
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d
this 
pattern is some 
pattern and we are going ahead

1
이것에서 1은 무엇을 하는가?
whatahitson 2016 년

1
@whatahitson 1은 Awk에서 축약 형으로 사용됩니다 {print $0}. 그 이유는 True로 평가되는 모든 조건이 현재 레코드 인쇄로 구성된 Awk의 기본 동작을 트리거하기 때문입니다.
fedorqui 'SO 중지 피해'

1

이것은 나를 위해 MAC에서 작동합니다

sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt

완벽한 지 아닌지 ...


1

이 질문에 대한 모든 답을 읽은 후에도 여전히 다음 예제 스크립트에 올바른 구문을 얻으려고 많은 시도가 필요했습니다.

#!/bin/bash
# script: add_domain
# using fixed values instead of command line parameters $1, $2
# to show typical variable values in this example
ipaddr="127.0.0.1"
domain="example.com"
# no need to escape $ipaddr and $domain values if we use separate quotes.
sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts

스크립트는 \n단일 sed명령을 사용하여 파일 끝에 줄 바꿈 과 다른 텍스트 줄을 추가합니다 .


1
sed -e 's/regexp/\0\n/g'

\ 0 은 null이므로식이 null (아무것도 아닌)로 바뀐 다음
\ n 은 줄 바꿈입니다.

유닉스의 일부 맛에서는 효과가 없지만 문제의 해결책이라고 생각합니다.

echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow

0

Red Hat의 vi에서는 \ r 문자 만 사용하여 캐리지 리턴을 삽입 할 수있었습니다. 나는 이것이 내부적으로 'sed'대신 'ex'를 실행한다고 생각하지만 비슷하지만 vi는 코드 패치와 같은 대량 편집을 수행하는 또 다른 방법이 될 수 있습니다. 예를 들어. 중괄호 뒤에 캐리지 리턴을 요구하는 if 문으로 검색어를 둘러 쌉니다.

:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/

일을 더 잘 맞추기 위해 몇 가지 탭을 삽입했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.