null 일치 정규식이 sed와 grep에서 다르게 작동하는 이유는 무엇입니까?

null 일치 정규식이 sed와 grep에서 다르게 작동하는 이유는 무엇입니까?

예를 들어 Debian 또는 Debian 파생 시스템의 도구를 사용하면 N*빈 문자열과 일치하는 다음과 같은 정규 표현식이 sed에서 일치할 수 있습니다.

$ echo 'Hello' | sed 's/N*/ xx&xx /g'
  xxxx H xxxx e xxxx l xxxx l xxxx o xxxx

xxxx이는 각 문자열 문자 앞의 빈 일치(즉, 사이에 문자가 없는 문자열)의 올바른 결과입니다 xx&xx( 에서 6회 Hello. 후행 줄 바꿈은 계산되지 않으며 일치하지 않습니다).

xx그리고 문자(또는 문자 그룹)가 일치하면 및 사이에 표시됩니다 xx.

$ echo  'Hello' | sed 's/e*/ xx&xx /g'
 xxxx H xxexx l xxxx l xxxx o xxxx

그러나 grep의 동일한 정규식은아니요빈 문자열과 일치합니다:

$ echo 'Hello' | grep -o 'N*'

하지만 인쇄할 거예요오직비어 있지 않은 일치:

$ echo 'Hello' | grep -o 'e*'
e

정규식 일치를 피하기 위해 grep에 추가 내부 규칙이 있습니까 empty?

답변1

grep -ogrep --help다음 과 같이 기록됨

  -o, --only-matching       show only nonempty parts of lines that match

그리고설명서에~처럼

일치하는 줄의 일치하는(비어 있지 않은) 부분만 인쇄하며, 각 부분은 별도의 출력 줄에 표시됩니다.

그렇습니다. 추가 규칙이 있습니다 grep -o. 일치 항목이 비어 있지 않은 경우에만 출력됩니다.

에서는 echo 'Hello' | grep -o 'N*'정규 표현식이 일치하지만(반환 코드를 보거나 사용하여 알 수 있음 echo 'Hello' | grep 'N*') 일치 항목이 비어 있으므로 아무것도 출력되지 않습니다.

답변2

길이가 0인 문자열 일치의 동작은 코드에서 특별한 경우일 수도 있고 아닐 수도 있습니다. 예를 들면 sed아니지만perl

$ echo aabb | sed 's/a*/X/g'
XbXbX
$ echo aabb | gsed 's/a*/X/g'
XbXbX
$ echo aabb | perl -ple 's/a*/X/g'
XXbXbX

행동은 vi가 역사적으로 어떻게 행동했는지에 따라 달라질 수 있습니다.깊이에서 볼 수 있듯이 ex/ex_subst.c:

    /*
     * !!!
     * It's possible to match 0-length strings -- for example, the
     * command s;a*;X;, when matched against the string "aabb" will
     * result in "XbXbX", i.e. the matches are "aa", the space
     * between the b's and the space between the b's and the end of
     * the string.  There is a similar space between the beginning
     * of the string and the a's.  The rule that we use (because vi
     * historically used it) is that any 0-length match, occurring
     * immediately after a match, is ignored.  Otherwise, the above
     * example would have resulted in "XXbXbX".  Another example is
     * incorrectly using " *" to replace groups of spaces with one
     * space.

(또 다른 문제는 너비가 0인 일치 항목이 절대 일치하지 않는다는 점입니다. 이를 방지하기 위해 "다음 문자로 이동합니다..." 코드가 추가될 수 있다고 확신합니다.뒤쪽에누군가의 CPU가 몇 번 100%에 도달했고 그의 손바닥이 이마에 닿았습니다. )

BSD와 GNU는 모두 표현식 ed에 실패하므로 s/a*/X/g특이한 동작 ex-vised?

$ echo aabb > foo
$ ed foo
5
s/a*/X/g
?
s/a*/X
Xbb
Q

답변3

$ echo 'Hello' | grep -o 'N*'
$ echo $?
0

그것하다종료 상태로 표시된 대로 이 입력 줄의 빈 부분 문자열과 일치합니다. (예를 들어 다른 모드를 사용하면 Nstdout에서는 아무것도 얻지 못하지만 종료 상태는 1,failure입니다.)

-o그러지 않도록인쇄빈 일치 항목이 있지만 정규 표현식이 입력 행과 일치하는지 여부와는 아무런 관련이 없습니다. (예, 차이점을 알 수 있습니다. 빈 문자열 일치를 인쇄하면 각 일치 후에 줄 바꿈을 인쇄하므로 프롬프트 앞에 빈 줄이 있습니다. 또는 각 일치에 대해 하나씩 6이 됩니다.)

그렇지 않은 경우 -o일치하는 전체 줄을 인쇄합니다.

$ echo 'Hello' | grep  'N*'          # same as grep '' empty pattern
Hello

관련 정보