나는 sed에 해당하는 것을 원합니다: . 출력에 대해 추가 처리를 수행하고 싶다고 가정해 보겠습니다. 이 단계는 아마도 더 긴 sed 표현식을 추가하면 더욱 복잡해지는 작업의 첫 번째 부분일 것입니다.grep -Eo 'regex'
; s…
좀 더 명확하게 말하자면, 각각을 분리할 수 있기를 원합니다.끈 입력 스트림에 제공된 정규식과 일치합니다. 개념 증명을 위해 이러한 각 문자열은 컨텍스트 없이 별도의 줄로 출력되어야 합니다(즉, 입력에 주변 텍스트가 없음). 따라서 여러(겹치지 않는) 일치 항목이 있는 입력 줄은 여러 출력 줄을 생성해야 하며, 일치 항목이 없는 입력 줄은 출력을 생성하지 않아야 합니다.
예:
정규식: [a-zA-Z]{3}[0-9]{4}
(즉, 세 글자 뒤에 네 개의 숫자가 옵니다)
입력하다:
FGH1234 and CAS4057
MAX2345
산출:
FGH1234
CAS4057
MAX2345
답변1
길이가 0인 정규식 일치 동작을 수정하도록 업데이트되었습니다.
sed 't match;s/REGEX/\n&\n/g;D;:match;/^\n/!P;s/\n//;D' file
일치 항목을 전역적으로 교체합니다 . 그런 다음 일치하는 부분이 모두 인쇄될 때까지 <newline><matched part><newline>
루프를 만들어 인쇄합니다 . 비어 있지 않은 일치 항목만 인쇄하려면(GNU처럼 ) just 대신 just를 사용하세요 .P;s/\n//;D
t match
/^\n/!P
P
grep -o
유사한 방법을 사용할 awk
수 있습니다:
regex='REGEX' awk 'BEGIN {FS="\n"}
gsub(ENVIRON["regex"], FS "&" FS) {for (i=2;i<NF;i+=2) if ($i!="") print $i}
' file
원래 시도: .*
빈 문자열과 일치하는 정규식(예를 들어)이 주어지면 이러한 명령은 잘못 작동합니다. 빈 줄은 무한 루프로 인쇄됩니다.
한 번의 통화로 sed
:
sed '
t match
s/[[:alpha:]]\{3\}[[:digit:]]\{4\}/\
&\
/;D;:match
P;D' file
POSIX 구문 사용 : 정규식은 대체 문자열에서 이스케이프된 줄바꿈을 사용 하고 분기 레이블 뒤에 줄바꿈을 사용하는 sed
기본 정규식입니다 . 일부 버전 (예: GNU sed)은 한 줄에 모든 스크립트를 허용할 수 있습니다.\
s///
;
sed
sed 't match;s/[[:alpha:]]\{3\}[[:digit:]]\{4\}/\n&\n/;D;:match;P;D' file
교체는 일치하는 부분 앞뒤에 개행 문자를 추가하여 첫 번째 일치 항목을 분리합니다. t match
스크립트 시작 부분의 조건 분기는 대체가 성공한 후에만 이어집니다. :match
일치하는 부분이 인쇄되는 곳입니다. D
패턴 공간에서 일치 항목이 포함된 줄을 제거하고 나머지를 다음 루프의 입력으로 사용하여 더 많은 일치 항목을 찾을 수 있도록 하는 데 사용됩니다.
답변2
이는 다음과 매우 유사합니다.조정 답변(그러나 독립적으로 개발됨) 약간 더 자세한 설명이 있을 수 있습니다.
GNU sed 사용:
sed -En 't dummy; : dummy; s/[a-zA-Z]{3}[0-9]{4}/&\n/; T; s/.*([a-zA-Z]{3}[0-9]{4}\n)/\1/; P; D'
설명하다:
-E
확장 정규식(ERE)을 사용합니다. 이것이 없다면 우리는\{3\}
평화 라고 말해야 할 것입니다\{4\}
.n
아무것도 자동으로 인쇄하지 마세요. 인쇄할 내용만 인쇄하세요. 이는 처럼grep
정규식과 일치하는 문자열을 포함하지 않는 입력 줄에 대해서는 아무것도 인쇄하고 싶지 않기 때문에 바람직합니다 .t dummy; : dummy
다음("dummy
") 레이블로 이동합니다. 이는 조건부 점프이므로 발생할 수도 있고 발생하지 않을 수도 있습니다. 하지만 점프 명령과 라벨 사이에는 아무 것도 없기 때문에 문제가 되지 않습니다.이것은 성공적인 작업이 있었는지 확인하기 위해 sed의 메모리를 지운다는 점을 제외하면 아무 작업도 하지 않는 것처럼 보입니다.에스대체 명령.
s/[a-zA-Z]{3}[0-9]{4}/&\n/
OP의 정규식을 찾으십시오. 발견되면 그 자체와 개행 문자로 대체됩니다(즉, 개행 문자가 추가됩니다).T
위의 대체 명령이 실패하면(패턴을 찾을 수 없음) 스크립트 끝으로 점프하고 다음 입력 줄을 읽습니다. 문서왜냐하면T
,T label
-
입력 라인을 마지막으로 읽은 이후와 마지막 또는 명령 이후 성공적인 대체가 없으면 다음
s///
으로 분기합니다.t
T
label
;만약에label
생략, 스크립트 끝으로 분기됩니다. 이것은 GNU 확장입니다.이것이 바로 우리가
dummy
이 라벨을 사용하는 이유입니다.이것T
이 명령은 이전 명령만 살펴봅니다s
.s/.*([a-zA-Z]{3}[0-9]{4}\n)/\1/
OP 앞에 임의 개수의 문자가 오는 것을 찾는 정규식(.*
) 뒤에 개행 문자가 오고 이를 정규식 일치 및 개행 문자로 바꿉니다(예: 정규식 일치 앞의 모든 텍스트 제거). 얼핏 보면 이렇게 보이는데 마지막그냥 일치 왜냐면.*
욕심을 부리세요. 그러나 첫 번째 일치 항목에만 개행 문자가 따라왔기 때문에 첫 번째 항목을 찾았습니다s
.G현지의).P
(수도인) 첫 번째 개행 문자 이후에 패턴 버퍼를 인쇄합니다. 이는 정규식과 일치하는 문자열입니다(grep -o
출력과 동일).D
첫 번째 개행 문자로 패턴 버퍼를 삭제하고 스크립트의 시작 부분으로 이동합니다.
답변3
파이프에서 GNU sed를 두 번 호출하면 grep과 동일한 출력이 제공됩니다.
sed -E 's/[a-zA-Z]{3}[0-9]{4}/\n&\n/g' input \
| sed -E '/^[a-zA-Z]{3}[0-9]{4}$/!d'
개념적으로:
sed -E 's/REGEX/\n&\n/g' input \
| sed -E '/^REGEX$/!d'
첫 번째 호출은 주변 개행 문자에서 일치하는 정규식을 분리합니다.
두 번째는 deletes
정규식과 일치하지 않는 모든 줄을 호출합니다.
실제로 정규식과 정확히 일치하는 행만 인쇄합니다 grep -o
.
일부 확장된 정규식을 사용하여 앞이나 뒤의 원하지 않는 부분을 일치시키고 제거하려고 하면 실패를 의미합니다. 정규식 엔진은 *
제한 없이 너무 많은 항목(모든 항목 때문에)과 일치하므로 일치합니다 as much as possible
. Lookaround Matching을 사용하여 PCRE를 구축하면 이 문제를 해결할 수 있지만 sed(현재 모든 sed)는 PCRE를 사용할 수 없습니다.
이 해결 방법은 간단하며 알려진 문제가 없습니다(정규식이 "없음"과 일치할 수 있는 경우 빈 줄이 많이 인쇄되는 경우 제외).
이 사용량을 sed 한 줄로 줄이려는 것은 (놀랍게도) 상당히 복잡해집니다. 다른 답변은 몇 가지 특수 사례와 복잡한 sed 구문을 사용하여 이를 달성하려고 합니다.
우리는 보편적인 해결책을 찾기 위해 계속해서 노력할 것입니다.
답변4
GNU 사용sed
$ sed -Ez ':a;s/([a-zA-Z]{3}[0-9]{4})[a-z ]+/\1\n/;ta' input_file
FGH1234
CAS4057
MAX2345
사용sed
$ sed -E 's/([a-zA-Z]{3}[0-9]{4}) [^A-Z]*/\1\
/' input_file
FGH1234
CAS4057
MAX2345