sed를 사용하여 첫 번째 일치 후 줄 삽입


245

어떤 이유로 나는 이것에 대한 직접적인 대답을 찾을 수없는 것처럼 보이며 현재 약간의 시간 위기에 처해 있습니다. sed명령을 사용하여 특정 문자열과 일치하는 첫 번째 줄 뒤에 선택 텍스트 줄을 삽입하는 방법은 무엇입니까 ? 나는 가지고있다 ...

CLIENTSCRIPT="foo"
CLIENTFILE="bar"

그리고 줄 뒤에 줄을 삽입하고 싶습니다 CLIENTSCRIPT=...

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"

답변:


379

GNU sed를 사용하여 이것을 시도하십시오 :

sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file

in-place 를 대체 하려면 다음을 사용하십시오.

sed -i '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file

산출

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"

문서


감사! 파일의 내용을 인쇄하지 않고 파일에 다시 쓰려면?
user2150250

11
둘 다 GNU를 가정 sed합니다. 그것은 표준 sed구문이 아니며 다른 sed구현 에서는 작동하지 않습니다 .
Stephane Chazelas

다른 구분 기호를 사용했기 때문에이 기능을 사용하는 데 문제가있었습니다. RTFM'ing 후, 나는 정규 표현식을 \로 시작한 다음 구분 기호를 시작해야한다는 것을 깨달았습니다.
Christy

10
첫 경기에만 어떻게 적용됩니까? 일치 후에 텍스트를 추가하는 것이 분명하지만 첫 번째 일치에만 어떻게 알 수 있습니까?
모하메드 누 렐딘

7
이것은 매 경기마다 텍스트를 추가합니다.
schoppenhauer

49

표준 sed구문에 유의하십시오 (POSIX에서와 같이 모든 호환 sed구현 (GNU, OS / X, BSD, Solaris ...)에서 지원) :

sed '/CLIENTSCRIPT=/a\
CLIENTSCRIPT2="hello"' file

또는 한 줄로 :

sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file

( sed 스크립트 해석 을 구성하기 위해 -expressions (및 -files 의 내용 )이 개행과 결합됩니다 sed).

-i내부 편집에 대한 옵션도 지원 (FreeBSD의의와 같은) GNU 확장, 다른 구현입니다 -i ''그합니다.

또는 이식성을 위해 perl대신 사용할 수 있습니다 .

perl -pi -e '$_ .= qq(CLIENTSCRIPT2="hello"\n) if /CLIENTSCRIPT=/' file

또는 당신은 사용할 수 있습니다 ed또는 ex:

printf '%s\n' /CLIENTSCRIPT=/a 'CLIENTSCRIPT2="hello"' . w q | ex -s file

2
틀릴 수도 있지만 현재 sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file는 첫 번째 매개 변수 끝에서 따옴표를 이스케이프하고 명령을 중단합니다.
버려진 카트

1
Bourne의 쉘 csh또는 rc패밀리 에서 @AbandonedCart '...'는 백 슬래시가 특수하지 않은 강한 따옴표입니다. 내가 아는 유일한 예외는 fish껍질입니다.
Stephane Chazelas

1
MacOS의 터미널 (그리고 그다음에 터미널에서 실행되는 스크립트)도 예외입니다. 대체 구문을 찾았지만 어쨌든 감사합니다.
버려진 카트

1
@AbandonedCart, 그것은 다른 것입니다. macOS sed는 POSIX를 준수하지 않습니다. 그것은 이식성이 잘못되었다는 진술을합니다 (한 줄 변형의 경우). 개방형 그룹이 실제로 부적합하거나 표준에 대한 잘못된 해석인지 확인하도록 요청합니다.
Stephane Chazelas

19

다음 s명령을 사용하여 POSIX 호환 제품 :

sed '/CLIENTSCRIPT="foo"/s/.*/&\
CLIENTSCRIPT2="hello"/' file

1
... 새로운 줄 삽입을 지원합니다. 나는 그것을 좋아한다!
Stephan Henningsen

1
sed -e '/.../s/$/\' -e 'CLI.../'유효한 문자를 형성하지 않는 바이트 시퀀스를 포함하는 행의 문제점을 피하는 방법 도 참조하십시오 .
Stephane Chazelas

14

MacOS (최소한 OS 10)와 Unix에서 모두 작동하는 Sed 명령 (예 : Gilles (현재 허용되는 것)과 같이 압축이 필요하지 않음) :

sed -e '/CLIENTSCRIPT="foo"/a\'$'\n''CLIENTSCRIPT2="hello"' file

이것은 bash와 $ '\ n'평가 견적 스타일을 알고있는 다른 쉘에서도 작동합니다. 모든 것은 한 줄에있을 수 있으며 이전 / POSIX sed 명령에서 작동합니다. CLIENTSCRIPT = "foo"(또는 동등한 항목)와 일치하는 여러 행이있을 수 있으며 처음으로 추가 행만 추가하려는 경우 다음과 같이 다시 작업 할 수 있습니다.

sed -e '/^ *CLIENTSCRIPT="foo"/b ins' -e b -e ':ins' -e 'a\'$'\n''CLIENTSCRIPT2="hello"' -e ': done' -e 'n;b done' file

(이것은 줄 삽입 코드 다음에 파일의 나머지 부분을 순환하면서 첫 번째 sed 명령으로 다시 돌아 가지 않는 루프를 만듭니다).

주석에 줄이 나타나거나 들여 쓰기되거나 일치하는 패턴에 '^ *'를 추가 한 것을 알 수 있습니다. 100 % 완벽하지는 않지만 일반적 일 수있는 다른 상황에 적용됩니다. 필요에 따라 조정하십시오 ...

이 두 가지 솔루션은 새로운 삽입 라인에 이스케이프되지 않은 백 슬래시 또는 앰퍼샌드가 포함되어 있으면 sed로 해석되고 is-와 같이 동일하게 나오지 않는 문제를 해결합니다 \n. \0일치하는 첫 번째 줄이됩니다. 특히 $ {var //}을 사용하여 먼저 모든 것을 이스케이프 해야하는 변수 또는 다른 sed 문 등을 사용하여 줄을 추가하는 경우 특히 유용합니다.

이 솔루션은 스크립트에서 조금 덜 지저분합니다 (인용 부호와 \ n은 읽기 쉽지 않습니다). 줄의 시작 부분에 a 명령에 대한 대체 텍스트를 함수에서 넣지 않으려는 경우 들여 쓰기 된 선으로. $ '\ n'은 셸에서 줄 바꿈으로 평가되며 정규 '\ n'작은 따옴표로 묶은 값이 아닙니다.

나는 perl / awk가 더 읽기 쉽기 때문에 이길 수 있다고 생각하지만 충분히 길어지고 있습니다.


1
답변 감사합니다! 첫 번째는 AIX OS의 매력처럼 작동합니다.
abhishek

이 작업을 어떻게 수행하지만 여러 줄 삽입을 위해?
tatsu

1
POSIX sed는 백 슬래시 ( source )로 대체 할 경우 대체 문자열에서 리터럴 개행을 지원합니다 . 따라서 : s/CLIENTSCRIPT="foo"/&\ [Enter] CLIENTSCRIPT2="hello"/ . 백 슬래시는이 주석에서 보이는 방식과 달리 줄의 마지막 문자 여야합니다 (뒤에 공백 없음).
TheDudeAbides

1
@tatsu 뉴 라인의 대체 문자열에서 s///뿐만 아니라에서와 ai명령은 내가 위에서 내 댓글에 설명하는 같은 방법을 사용하여 "탈출"할 수 있습니다.
TheDudeAbides 19

4

어쩌면 이것에 대한 답변을 게시하는 데 약간 늦었지만 위의 솔루션 중 일부는 약간 성가신 것으로 나타났습니다.

sed에서 간단한 문자열 교체를 시도했지만 작동했습니다.

sed 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file

& 기호는 일치하는 문자열을 반영한 다음 \ n과 줄 바꾸기를 추가합니다.

언급했듯이 제자리에서 수행하려면 다음을 수행하십시오.

sed -i 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file

또 다른 한가지. 표현식을 사용하여 일치시킬 수 있습니다.

sed -i 's/CLIENTSCRIPT=.*/&\nCLIENTSCRIPT2="hello"/' file

이것이 누군가를 돕기를 바랍니다.


이것은 \n대체 문자열을 이해하기 때문에 GNU sed가 기본값 인 Linux에서 제대로 작동 합니다. 그러나 일반 문자열 (POSIX) sed은 대체 문자열에서 이해 하지 \n 하므로 GNU sed를 어떻게 든 설치하지 않으면 BSD 또는 macOS에서 작동하지 않습니다. 바닐라 sed를 사용하면 줄 바꿈을 "이스케이프"하여 줄 바꿈을 포함 할 있습니다. 즉, 백 슬래시로 줄을 끝내고 [Enter] ( 참조 제목 [2addr]s/BRE/replacement/flags) 아래를 누릅니다 . 이것은 sed 명령이 터미널의 여러 줄에 걸쳐 있어야 함을 의미합니다.
TheDudeAbides 19

대체 문자열에서 리터럴 개행을 얻는 또 다른 옵션 은 다른 답변 중 하나 에서 언급 한 것처럼 Bash에서 ANSI-C 인용 기능 을 사용하는 입니다.
TheDudeAbides 19


1

나는 비슷한 작업을했고 위의 펄 솔루션을 작동시킬 수 없었습니다.

내 해결책은 다음과 같습니다.

perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf

설명:

정규식을 사용하여 /etc/mysql/my.cnf 파일에서 포함 된 줄만 검색 [mysqld]하고

[mysqld] collation-server = utf8_unicode_ci

collation-server = utf8_unicode_ci포함 하는 줄 뒤에 효과적으로 줄을 추가하십시오 [mysqld].


0

나는 최근에 Mac과 Linux OS 모두 에서이 작업을 수행해야했으며 많은 게시물을 탐색하고 많은 일을 시도한 후에, 특히 내가 원했던 곳에 도달하지 못한 적이 있다고 생각합니다. 간단한 패턴, 하나의 라이너, 휴대용, 확장 성을 갖춘 표준 명령으로 더 많은 제약을 추가 할 수 있습니다. 그런 다음 다른 관점으로 보았습니다. "2 라이너"가 나머지 기준을 충족하면 "하나의 라이너"옵션 없이도 할 수 있다는 것을 깨달았습니다. 결국 나는이 솔루션을 생각해 냈습니다. 우분투와 Mac에서 모두가 공유하고 싶었습니다.

insertLine=$(( $(grep -n "foo" sample.txt | cut -f1 -d: | head -1) + 1 ))
sed -i -e "$insertLine"' i\'$'\n''bar'$'\n' sample.txt

첫 번째 명령에서 grep은 "foo"를 포함하는 줄 번호를 찾고 cut / head는 첫 번째 항목을 선택하고 산술 연산은 발생 후 삽입하기 때문에 첫 번째 발생 줄 번호를 1 씩 증가시킵니다. 두 번째 명령에서는 인라인 파일 편집, "i"삽입 : ansi-c 인용 새 줄, "bar"및 다른 새 줄입니다. 결과는 "foo"행 뒤에 "bar"를 포함하는 새 행을 추가합니다. 이 두 명령은 각각 더 복잡한 조작 및 일치로 확장 될 수 있습니다.

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