그래서 한동안 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와 같을 때 해당 줄을 인쇄한 다음 주입하려는 내용을 인쇄합니다.
sed
Perl의 뿌리가 , , awk
및 에 있다는 점을 서둘러 덧붙이겠습니다. C
따라서 간단한 대체 등의 구문은 학습 곡선이 그리 험난하지 않습니다.
답변4
간단한 데모:
$ date | sed -E $'1i\\\nfoo\n'
foo
Thu Aug 6 07:09:01 CDT 2020
이것은 $'...'
이스케이프 시퀀스 확장을 강제하는 bashism입니다. 이를 사용할 때 문자열에서 텍스트를 가져오는 데 사용해야 합니다 \\
.\