sed에서 여러 개의 느낌표를 사용하는 요점은 무엇입니까?


12

POSIX sed 문서 는 말했다 :

함수 앞에는 하나 이상의 '!'가 올 수 있습니다. 이 경우, 주소가 패턴 공간을 선택하지 않으면 기능이 적용됩니다. 첫 번째 '!'앞에 0 개 이상의 <공백> 문자가 허용됩니다. 캐릭터. <blank> 문자가 '!'뒤에 올 수 있는지 여부는 지정되지 않았습니다. 문자, 그리고 적합한 응용 프로그램은 '!' <공백> 문자가있는 문자.

따라서 POSIX sed를 사용하면 다음을 수행 할 수 있습니다.

sed -e '/pattern/!d' file

쓰기와 동일합니다.

sed -e '/pattern/!!d' file

그리고 !!!dn느낌표의 마크는 여전히 (세 가지로 테스트 괜찮을 있습니다 sed에서 버전 가보 toolchest을을 ). 하나의 느낌표가 아닌 여러 개의 효과가 보이지 않습니다.

스펙이 그 구문을 허용하는 이유는 무엇이며 실제 응용에 유용합니까?


이 경우 GNU sed가 호환되지 않는 것 같습니다. 여러 개의 느낌표를 사용하면 불평합니다.

$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s

2
FWIW : OpenBSD !에서 토글의 역할을하고, /pattern/!!동일하고 /pattern/, /pattern/!!!동일합니다 /pattern/!. FreeBSD에서 다중 !은 단일 것과 동일합니다.
lcd047 2016 년

2
스펙에서 많은 것들의 요점은 sed스크립트가 생성 될 수 있다는 것 입니다. POSIX가 주어지면 sed스크립트 작성을 스크립트하는 것이 실제로 간단해야합니다 sed. 따라서 어떤 경우 !에든 어떤 동작에 적합하지 않은 주소를 표시 해야하는 경우에 대해 트리거가있는 경우 동일한 주소에 대해 여러 번 트리거해도 여전히 동일한 결과가 나올 수 있습니다.
mikeserv 2016 년

@cuonglm 아니요, FreeBSD 만 있습니다. GNU, OpenBSD 및 NetBSD sed는 그렇지 않습니다.
lcd047

@ lcd047 : 물론입니다. 내 하찮은 영어 실력에 죄송하다는 말씀을 드리고 싶습니다. 나는 그것이 준수하지 않는다는 것을 의미합니다. 그것을 아는 것이 좋습니다. 그러나 내 질문의 주요 요점은 POSIX sed를 사용하여 구문이 실제 세계에서 어떻게 유용 할 수 있습니까?
cuonglm 2016 년

1
FWIW : 이에 대한 수정 사항이 OpenBSD-current에서 커밋되었습니다.
lcd047

답변:


5

sed의 API는 원시적이며 의도적으로 설계된 것입니다. 적어도, 그것은했다 남아 디자인으로 원시 - 그것은 내가 말할 수 없다 처음에 원시적 설계되었는지 여부. 대부분의 경우, sed실행될 때 다른 sed스크립트 를 출력 하는 스크립트 작성 은 실제로 간단한 문제입니다. sed는 이런 식으로 m4and / or 같은 매크로 전처리기에 의해 매우 자주 적용됩니다 make.

(다음은 매우 가설적인 사용 사례입니다. 솔루션에 적합하도록 설계된 문제입니다. 문제가 발생했을 가능성이 높을 수 있습니다. 그러나 그것이 반드시 덜 유효한 것은 아닙니다.)


다음 입력 파일을 고려하십시오.

cat <<"" >./infile
camel
cat dog camel
dog cat
switch
upper
lower

위의 입력 파일에서 적절한 문맥 의 줄에서 찾을 수있는 경우에만 위의 입력 파일에서 각 적절한 단어 의 꼬리에 sed단어 -case 를 추가 하는 스크립트 를 작성하고 싶다면 가능한 한 효율적으로 수행하기를 원했습니다 ( 예를 들어 컴파일 작업 중에 목표가 되어야하는 경우 ) 정규 표현식 을 가능한 많이 적용하지 않는 것이 좋습니다.//

우리가 할 수있는 한 가지는 지금 시스템에서 파일을 미리 편집하고 sed컴파일하는 동안 전혀 호출하지 않는 것 입니다. 그러나 파일의 해당 단어 중 일부가 로컬 설정 및 / 또는 컴파일 타임 옵션을 기반으로 포함되거나 포함되지 않아야하는 경우, 그렇게하는 것이 바람직한 대안이 아닐 수 있습니다.

우리가 할 수있는 또 다른 것은 파일을 처리입니다 지금 regexps '에 대하여. 우리는 sed줄 번호에 따라 편집을 적용 할 수 있는 스크립트를 생성하고 컴파일에 포함 시킬 수 있습니다. 이 스크립트는 일반적으로 장기적으로 훨씬 더 효율적인 경로입니다.

예를 들면 다음과 같습니다.

n=$(printf '\\\n\t')
grep -En 'camel|upper|lower' <infile |
sed "   1i${n%?}#!/usr/heirloom/bin/posix2001/sed -nf
        s/[^:]*/:&$n&!n;&!b&$n&/;s/://2;\$a${n%?}q"'
        s/ *cat/!/g;s/ *dog/!/g
        s| *\([cul][^ ]*\).*|s/.*/\1-case/p|'

... sed스크립트 형태로 출력을 작성하고 다음과 같이 보입니다 ...

#!/usr/heirloom/bin/posix2001/sed -nf
:1
    1!n;1!b1
    1s/.*/camel-case/p
:2
    2!n;2!b2
    2!!s/.*/camel-case/p
:5
    5!n;5!b5
    5s/.*/upper-case/p
:6
    6!n;6!b6
    6s/.*/lower-case/p
q

해당 출력이 내 컴퓨터에서 실행 가능한 텍스트 파일로 저장 ./bang.sed되고 다음과 같이 실행 ./bang.sed ./infile되면 출력은 다음과 같습니다.

camel-case
upper-case
lower-case

이제 물어봐도 될까요grep ... 왜 내가 그렇게하고 싶습니까? 일치를 고정시키지 않습니까? 어쨌든 누가 낙타 상자를 사용합니까? 그리고 난 단지 답장을 할 수 각 질문에, 나는 ... 아무 생각이 내가하지 않기 때문에. 이 질문을 읽기 전에 나는 개인적으로 멀티를 눈치 채지 못했습니다 ! 사양의 구문 분석 요구 사항-꽤 깔끔한 생각이라고 생각합니다.

멀티! 가지 않았다 의 많은 -하지만 즉시 나에게 의미가 sed사양이 간단하게 분석하고 간단 위해 개발되어 생성 된 sed 스크립트. 해당 맥락에서 필요한 \newline 구분 기호를 찾을 수있을 것입니다. [wr:bt{]이 아이디어를 명심하면 사양의 다른 측면을 더 잘 이해할 수 있습니다 (예 : :주소 를 받아들이지 않고 q거부). 1) 이상을 수락하십시오 .

예제에서 나는 특정 형태 쓰는 이상 sed만 할 수 스크립트 이제까지 한 번 읽을 수있다. 당신이 그것을 열심히 보면 sed편집 파일 을 읽을 때 하나의 명령 블록에서 다음 명령 블록으로 진행 한다는 것을 알 수 있습니다 -편집 파일이 완전히 완성 될 때까지 편집 스크립트에서 멀어 지거나 편집 스크립트를 완료하지 않습니다.

나는 그 멀티를 고려합니다 ! 주소는 다른 것보다 그 맥락에서 더 유용 할 수 있지만, 정직하게 말해서, 나는 그것을 아주 잘 사용했을 수있는 단일 사례를 생각할 수 없습니다 sed. 또한 GNU / BSD sed모두 지정된대로 처리하지 못한다는 점에 주목할 필요가 있습니다. 이것은 많은 수요가있는 사양의 한 측면이 아니므로 구현이 간과되면 버그가 심각하게 의심 됩니다. 결과적으로 끔찍합니다.

말했다 즉, 실패는 규정이 처리하는 것입니다 준수에 대한 구현을위한 버그가있는 척, 나는라고-위해 여기에 관련 dev에 상자에 이메일을 촬영하는 생각 때문에, 나는 그렇게하지 않으면 그렇게 할 계획입니다.


1
이제 OpenBSD-current에서 수정되었습니다.
lcd047

1
다음 스펙! 에서 다중 이 제거 될 예정입니다.
cuonglm 2016 년

@ cuonglm-너무 늦었습니다. 어쩌면 내가 생각했던 것보다 마크에 더 가까이 있었을 것입니다.
mikeserv 2016 년

@cuonglm - 음, 좋아,하지만 ... 무엇을 수락를로가 표시된 경우에도 평균?
mikeserv

1
@ mikeserv : 대답은 내 경이를 설명하고 sed API로 또 다른 견해를주었습니다. 나에게 이해가된다!
cuonglm 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.