특정 라인에서 OSX 인서트에 sed


24

그래서 나는 리눅스에서 'sed'를 잠시 동안 사용했지만 'POSIX sed'와 'GNU sed'에는 많은 차이가 있기 때문에 OSX에서 사용하려고 시도하는 데 약간의 어려움이있었습니다. 현재 특정 줄 번호 뒤에 텍스트 줄을 삽입하는 방법에 어려움을 겪고 있습니다. (이 경우 4 행)

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

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

그래서 OSX에서 나는 이것을 시도했다 :

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

그러나 이것은 '명령 끝에 \ 뒤에 추가 문자'라는 오류가 계속 발생합니다. 여기에 무슨 문제가 있습니까? 오타가 있습니까? 또는 sed 버전의 다른 차이점을 이해하지 못합니까?


2
MacOS 10.6.8에서 작동하지 않는 것을 확인할 수 있습니다. 데비안 6.0.3에서 잘 작동합니다.
tink

답변:


24

엄밀히 말해 POSIX 사양은sed 다음 a\과 같이 개행이 필요합니다 .

[1addr]a\
text

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

이것은 한 라이너 아마 다음과 같은 이유이다 고통의 비트 작성하게 GNU 확장 받는 사람 a, i그리고 c명령을 :

GNU 확장으로서 a, 개행과 개행 사이 에 공백 \순서 이외의 문자가 있으면 ,이 행의 문자는. 다음의 공백 이 아닌 첫 문자부터 시작 a하여 텍스트 블록 의 첫 번째 행으로 간주됩니다 . 이렇게하면 한 줄 추가 스크립트를 간단하게 작성할 수 있습니다.이 확장은 또한 iand c명령 과 함께 작동 합니다.

따라서 sed구문을 이식하기 위해서는 a\어떻게 든 줄 바꿈을 포함해야합니다 . 가장 쉬운 방법은 인용 된 줄 바꿈을 삽입하는 것입니다.

$ sed -e 'a\
> text'

(여기서 $>셸 프롬프트이다). bash[1] $' '에 C 스타일 이스케이프를 삽입 하는 인용구 가 있다면 ,

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

[1] 및 mksh (r39b +) 및 비 -bash 본 쉘 (예 : FreeBSD 9+의 / bin / sh)


매우 유익한 답변. bash quot 구문에 대한 힌트를 주셔서 감사합니다.
cjackson

14

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

이 특정 경우에, 당신이하려는 것은 실제로 하나의 -e ...절로 달성 될 수 있습니다 . a명령을 올바르게 사용해야 합니다. POSIX 표준 a에 따라 \, 그 뒤에 개행 문자가오고, 그 다음에 개행 문자가오고, 다음 행의 나머지 부분이 삽입됩니다 (개행 문자 또는 -e절의 끝이 나올 때까지 ). 그래서 당신은 할 수 있습니다 :

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

2
당신은 당신은 GNU-ISMS를에 의존하고 봤는데 어떤 기능 분류 할 경우,이 페이지가 도움이 될 수 wiki.alpinelinux.org/wiki/Regex를 . 그러나 정규식 기능으로 만 제한됩니다. 다른 sed 명령이 아닙니다.
dubiousjim

5

GNU sed는 어쨌든 내가 사용한 예제 / 튜토리얼을 기반으로 POSIX sed보다 훨씬 일반적으로 사용되는 것 같습니다.

내가 사용하는 OSX 시스템에 GNU sed를 설치하는 것이 훨씬 쉽다는 것을 알았습니다. 관심이 있으시면 Homebrew를 통해 설치하는 것이 가장 좋습니다 .

$ brew install gnu-sed사용하거나을 사용하여 모든 일반적인 GNU 유틸리티를 얻을 수 있습니다 $ brew install coreutils.

그런 다음 구문 date이나 다른 프로그램에 문제가 발생 하면 GNU 버전을 사용할 수 있습니다. 결국 나는 항상 GNU 버전을 사용하는 것이 더 쉬워서 시스템 버전보다 더 일찍 내 버전에 넣기로 결정했다 PATH.


5

Perl은 이러한 플랫폼 의존 GNU 대 비 GNU 대 "독점"특유의 문제로 고생하지 않습니다. 당신은 할 수 있습니다 :

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

-n' option creates a loop that reads every line of the input file. Unlike its cousin-p (not used here) it doesn't automatically print every line read. The-i invokes in-place replacement. The argument to-i는 (viz. ".old") can be dropped or changed. It leaves a backup of the unmodified file. The -e스크립트의 시작을 알립니다.

$.라인 1로 시작하는 라인 번호를 나타낸다. 따라서 명령 행은 'file'을 읽고 행 번호가 4와 같으면 해당 행 다음에 주입하려는 항목을 인쇄합니다.

나는 Perl이 sedAWK와 C에 뿌리를두고 있기 때문에 간단한 대체 등을위한 구문이 매우 가파른 학습 곡선이 아니라고 덧붙였다.


좋은 대답입니다! 그러나 약간 단순화 할 수 있습니다. 이것을 시도하십시오 : perl -wlpi.old -e 'print "mode 0755" if $. == 5' file.txt. -p(우리는 모든 라인을 인쇄 할 때문에) 스위치는 여기에 잘 작동한다; 우리는 로직을 " 라인 4 이후 인쇄 "에서 " 라인 5 이전 인쇄" 로 변경해야합니다 . 또한 -l스위치를 사용하면 "\ n"이 (가) 자동으로 print인쇄되므로 직접 인쇄 할 필요가 없습니다.
JL
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.