이 스레드는 이 스레드에 대한 링크에 있는 산술 명령에 의해 동기가 부여됩니다.여기Sed에서 역방향 산술을 수행하고 싶습니다.
데이터
Mikael symptom
David symptom
hello symptom
이 명령은 처음 두 항목을 반환해야 합니다. Perl의 Lookbehind는 한 가지 방법이지만 Sed가 그것을 할 수 있는지 확인하고 싶었습니다.
의사코드의 메소드
- 일치하는 이름:
g/[A-Z]\w\w/
;is.words[2]('symptom')
뒤를 봐
- Match
symptom
; 다음 이름을 찾습니다. 이름이 있으면 반환합니다.
Sed에서 이 의사코드를 작성할 수 있나요?
답변1
sed '/^[[:upper:]][[:lower:]]\{1,\} symptom$/!d
H;x;/^\n/!q;s///;x;d'
이렇게 하면 대문자로 시작하고 그 뒤에 하나 이상의 소문자가 오는 줄을 찾은 다음 하나만 찾습니다.<스페이스>그리고 문자열징후. 현재 줄이 일치하지 않으면 d
삭제되고 다음 입력 줄부터 스크립트가 맨 위에서 다시 시작됩니다.
그 경우하다일치 항목은 H
삽입된 줄 구분 기호 뒤의 이전 공백 에 복사됩니다 \n
. 이런 일이 처음 발생하면 h
기존 공간은 비어 있을 것이므로 주인공은 \n
유라인이 됩니다. 일치하는 라인이 H
삭제 된 후 h
이전 및 패턴 공간이 x
e에 의해 변경됩니다. 만약 있다면!
아니요\n
패턴 공간에서 ewline을 리드한 다음 sed
q
입력을 충족합니다. 갑자기 추가 입력 읽기가 중단되었습니다.(또는 스크립트에서 더 많은 명령을 실행합니다. 예를 들어 d
)별말씀을요. 그러나 리딩 \n
라인이 제거되고 h
오래된 패턴 공간이 x
다시 변경되어 패턴 공간이 d
제거됩니다.
결과적으로 처음 만난 행은 유지되고 그것이 나타내는 첫 번째 발생 태그는 이를 q
uitting 입력에서 저장하지만두번째발생하면 처리를 종료합니다.
하지만 내가 오해한 건 아닐까? 파일에서 처음 두 개의 일치 항목만 원한다는 것이 무슨 뜻인지 이해합니다.
당신이 원한다면이름만약에증상$이것은 매우 간단합니다.
sed -n '/^[[:upper:]][[:lower:]]\{1,\} [^ ]*$/s/ symptom$//p'
여기서는 우리가 실제로 찾고 있는지 확인합니다.가능한교체를 시도하기 전에 라인을 일치시키세요 s///
- s///
교체가 다음과 같기 때문입니다.기능부모 주소. true인 경우 원하지 않는 꼬리를 잘라내고 p
성공할 경우 에만 인쇄하려고 합니다 .둘 다머리와 꼬리 상태를 확인하기 전에.
답변2
내가 이해하는 바에 따르면, 대문자 단어와 그 뒤에 대문자 단어가 포함된 줄을 인쇄하고 싶습니다 symptom
. 이 경우:
$ sed -rn '/\b[[:upper:]][[:lower:]]*[[:space:]]+symptom/p' data
Mikael symptom
David symptom
편의상 \b
which를 사용하여 단어 경계를 나타냅니다. 이는 최소한 GNU sed에서 지원됩니다. 귀하의 sed가 지원하지 않는 경우 알려주십시오.
작동 방식:
기본 형태는 다음과 같습니다.
sed -n '/pattern/p' file
이것은 일치하는 줄만 인쇄합니다 pattern
. 우리의 경우 패턴에는 다음이 포함됩니다.
\b
이는 단어 경계에서만 일치합니다.
[[:upper:]][[:lower:]]*
이는 대문자 뒤에 0개 이상의 소문자가 오는 것과 일치합니다.
고대에는 이것이 이렇게 쓰여졌을 수도 있다는 점에 유의하십시오
[A-Z][a-z]+
. 유니코드로 인해 현재는 신뢰할 수 없습니다. 위의 내용은 문자 클래스를 사용하므로upper
유니lower
코드에 안전합니다.[[:space:]]+symptom
이는 하나 이상의 공백 뒤에 단어가 오는 것과 일치합니다
symptom
.
선택하다
앞의 이름만 인쇄하고 싶다고 가정해 보겠습니다 symptom
.
$ sed -rn 's/\b([[:upper:]][[:lower:]]*)[[:space:]]+symptom.*/\1/p' data
Mikael
David
답변3
sed -n '/^[[:upper:]]\w* symptom/s/ .*//p'
대문자로 시작하는 줄을 인쇄한 symptom
다음 첫 번째 단어를 제외한 모든 항목을 삭제합니다.