OSX의 sed는 특정 라인에 삽입됩니다.

OSX의 sed는 특정 라인에 삽입됩니다.

그래서 한동안 Linux에서는 "sed"를 사용해왔지만, OSX에서는 "POSIX sed"와 "GNU sed" 사이에 미묘한 차이가 많아서 사용하는데 약간 어려움을 겪었습니다. 현재 특정 줄 번호 뒤에 텍스트 줄을 삽입하는 방법에 어려움을 겪고 있습니다. (이 경우 4번째 줄)

리눅스에서는 다음과 같이 할 것입니다:

sed --in-place "4 a\  mode '0755'" file.txt

그래서 OSX에서는 다음을 시도했습니다.

sed -i "" "4 a\ mode '0755'" file.txt

그러나 이로 인해 "명령 끝에서 \ 뒤에 추가 문자" 오류가 계속 발생합니다. 여기서 무슨 일이 일어나고 있는지 아이디어가 있습니까? 제가 오타를 냈나요? 아니면 내가 이해하지 못하는 sed 버전 사이에 또 ​​다른 차이점이 있습니까?

답변1

엄밀히 말하자면,POSIX 사양sed그 후에 포장해야 합니다 a\.

[1addr]a\
text

앞에서 설명한 대로 표준 출력에 텍스트를 씁니다.

이로 인해 재치 있는 말을 쓰는 것이 약간 고통스럽습니다. 아마도 다음과 같은 이유 때문일 것입니다.GNU 확장a, i및 명령 으로 c:

GNU 확장으로서, a개행과 개행 사이에 일련의 공백 이외의 것이 있는 경우, \다음의 공백이 아닌 첫 번째 문자로 시작하는 텍스트 a텍스트막혔습니다. (이것은 한 줄 추가 스크립트 작성을 단순화할 수 있습니다.) 이 확장은 i및 명령 과 함께 사용할 수도 있습니다 c.

따라서 구문과 호환되도록 하려면 sed구문 뒤에 개행 문자를 추가해야 합니다 a\. 가장 쉬운 방법은 인용된 개행 문자를 삽입하는 것입니다.

$ sed -e 'a\
> text'

( 쉘 프롬프트는 어디에 $있고 어디에 있습니까?) >통증이 느껴 bash지면 [1]$' 'C 스타일 이스케이프를 삽입하는 인용 구문이므로 그냥 사용하세요.

sed -e 'a\'$'\n''text'

[1] 버전 2.0(1996) 및 ksh93(해당 소스) 이후, zsh(3.1.5+), mksh(r39b+) 및 일부 Almquist 쉘 파생물(예: FreeBSD 9+의 /bin/sh)

답변2

에서 언급했듯이이 답변i, 및 와 같은 sed 명령을 사용할 때 a여러 절을 사용하는 것이 도움이 됩니다 -e "...". 이러한 각 절은 개행 문자로 구분되는 것으로 이해됩니다. 그렇지 않으면 i및 명령은 a인라인 sed 스크립트에서 사용하기 어렵습니다(이들은 이라는 여러 줄의 sed 스크립트 파일에서 사용되도록 설계되었습니다 sed -f file ...). 추가할 텍스트 줄을 -e구분하기 위해 절 끝에 도입된 암시적 개행 문자를 사용할 수 없는 것 같습니다 . a\그러나 추가하려는 텍스트 줄을 종료하는 데 사용할 수 있습니다.

이 특별한 경우에는 원하는 작업을 실제로 -e ...단일 절로 수행할 수 있습니다. a명령을 올바르게 사용 하면 됩니다 . POSIX 표준에 따르면, a\뒤에 개행 문자가 와야 하며, 그 다음에는 다음 줄의 나머지 부분이 삽입됩니다( -e개행 문자나 절의 끝이 나타날 때까지). 그래서 당신은 이것을 할 수 있습니다 :

sed -i "" -e $'4 a\\\n'"mode '0755'" file.txt

답변3

Perl은 플랫폼 의존적인 GNU, 비 GNU, "독점" 특성으로 인해 어려움을 겪지 않습니다. 다음을 수행할 수 있습니다.

perl -ni.old -e 'print;if ($.==4) {print "mode 0755\n"}' file

-n옵션은 입력 파일의 각 줄을 읽는 루프를 만듭니다. 사촌 -p(여기에서는 사용되지 않음)과 달리 읽는 모든 줄을 자동으로 인쇄하지 않습니다. -i내부 교체를 호출합니다 . -i(예: ".old") 매개변수는 제거되거나 변경될 수 있습니다. 수정되지 않은 파일의 백업을 남깁니다. -e스크립트의 시작을 표시합니다 .

$.라인 1부터 시작하여 라인 번호를 나타냅니다 . 따라서 명령줄은 을 읽고 file줄 번호가 4와 같을 때 해당 줄을 인쇄한 다음 주입하려는 내용을 인쇄합니다.

sedPerl의 뿌리가 , , awk및 에 있다는 점을 서둘러 덧붙이겠습니다. C따라서 간단한 대체 등의 구문은 학습 곡선이 그리 험난하지 않습니다.

답변4

간단한 데모:

$ date | sed -E $'1i\\\nfoo\n'
foo
Thu Aug  6 07:09:01 CDT 2020

이것은 $'...'이스케이프 시퀀스 확장을 강제하는 bashism입니다. 이를 사용할 때 문자열에서 텍스트를 가져오는 데 사용해야 합니다 \\.\

관련 정보