grep의 그룹 일치에 추가 문자가 포함되어 있습니다.

grep의 그룹 일치에 추가 문자가 포함되어 있습니다.

Bash에서 정규식을 사용하여 일부 텍스트를 추출하고 싶었기 때문에 다음과 같은 간단한 예제를 시도해 보기로 결정했습니다.

echo "abc def ghi" | grep -Po " \K(.*?) "

나는 을 얻을 것으로 예상했지만 "def"놀랍게도 "def "(끝에 추가 공간이 있음)을 얻었습니다.

grep끝에 여분의 공간이 포함된 이유와 이를 제거하는 방법에 관심이 있습니다 . 다른 줄을 사용하여 결과를 사후 처리할 수 있다는 것을 알고 있지만 이 문제를 해결하는 데 관심이 있습니다.

답변1

간단히 말해서:

\K

grep이 모든 것을 유지하게 만듭니다.이전에\K로 변환하고 일치 항목에 포함하지 않습니다. 이것은 다음에 일어날 일에 영향을 미치지 않습니다뒤쪽에이것 \K().

이것으로 충분할 수 있습니다:

" \K(.+)(?= )"

(?= )비캡처 그룹은 어디에 있나요?

아니면 더 좋을 수도 있습니다:

" \K([^ ]+)(?= )"
" \K(\w+)(?= )"

또는 유사합니다.

답변2

수행하려는 작업을 수행하는 BRE는 sed다음과 같습니다.

sed 's/ *\(\([^ ]*\) *\)\{[num]\}.*/\2/'

sed...또는 GNU 및 BSD 버전과 같이 이를 지원하는 ERE로 :

sed -E 's/ *(([^ ]*) *){[num]}.*/\2/p'

[num]...어느 표현식이든 그룹의 첫 번째 문자부터 시작하여 일치합니다.(여기서 [num]양의 정수는 무엇입니까?)패턴 공간의 공백이 아닌 문자를 검색 [^ ]*하고 줄 끝까지 일치를 계속합니다.

그러나 중요한 것은 일부 일치 항목을 그룹화한다는 것입니다.

  • (([^ ]*) *){[num]}- 이 그룹은 공백이 아닌 그룹 및 다음 공백 문자의 일부/모두만큼 많이 발생하며 [num]역참조로 사용할 수 있습니다 \1.
    • {[num]}- 패턴이 \{[num]\}여러 번 일치하는 경우 해당 패턴에 대한 유일한 참조는 마지막 패턴입니다. 따라서 그룹이 지정된 패턴과 여러 번 일치하는 경우에도 반환되는 유일한 참조는 마지막 패턴입니다.
  • ([^ ]*)- 그러나 위 그룹의 하위 그룹은 에서 일치하는 공백이 아닌 문자의 하위 집합에만 일치합니다 \1. 이 하위 그룹은 에서 참조될 수 있습니다 \2.
  • *And .*- 이는 패턴 공간으로 이어지는 모든 공백 문자와 하위 표현식에서 일치하는 항목 다음에 나오는 모든 문자와 일치합니다.
  • /\2/- 위의 모든 항목이 에서 참조된 그룹으로 대체됩니다 \2.

[^ ]*and는 부울 보수 *이고 [^ ]*U를 *함께 사용하면 가능한 모든 문자열을 설명할 수 있으므로 위의 정규식은 보편적입니다.

귀하의 예를 들어:

for n in 1 2 3 4
do  echo "abc def ghi" | 
    sed -E "s/ *(([^ ]*) *){$n}.*/\2/"
done | sed -n l

...인쇄...

abc$
def$
ghi$
$

있는 그대로는 위에서 요청한 특정 이벤트에 대해 항상 빈 줄을 인쇄하지만, 원하지 않는 경우 다음과 같이 줄을 출력에서 ​​완전히 제거할 수 있습니다.

sed -En 's/ *(([^ ]*) *){[num]}.*/\2/;/./p'

한 단계 더 나아가서 대체를 전역적으로 적용하여 모든 발생 항목만 얻을 수 있습니다 [num]. 매우 제한적 이므로 대신 *이것을 사용하겠습니다 . [[:space:]]*어떤 <space><tab><newline><vertical tab><return>.

s=
{   printf "${s:=$(printf '\r\v\t%10s')}"
    seq -s"$s" 100
} | sed -En "s/[${s:=[:space:]}]*(([^$s]*)[$s]*){21}/\2\\
/g;      /[^$s]/s/\n*$//p"

sed위의 비트는 적용되기 전에 printf ...; seq ...한 줄을 인쇄합니다 . 예를 들면 다음과 같습니다.

\r\v\t          1\r\v\t          2\r\v\t          3\r\v\t...

... 등. 그러나 위의 결과를 적용하면 sed다음과 같습니다.

21
42
63
84

...뒤에 공백 없이 숫자를 인쇄합니다.

관련 정보