질문

질문

나는 대답했다슈퍼유저에 대한 질문이는 grep 출력에 사용되는 정규식과 관련이 있습니다.

제가 드린 답변은 이렇습니다.

 tail -f log | grep "some_string.*some_string"

그런 다음 내 답변에 대한 세 가지 의견에서@단발다음과 같이 썼습니다:

.*욕심을 부리면 원하는 것보다 더 많은 것을 잡을 수 있습니다. .*?일반적으로 더 좋습니다.

그래서 이거,

이는 기본 욕심이 있는 대신 게으른 것으로 만드는 ?수정자입니다 . *PCRE를 가정합니다.

검색했지만 PCRE내 답변에서 이것이 무엇을 의미하는지 이해할 수 없습니까?

이 마지막 것,

또한 이것은 쉘 glob이 아니라 정규식(grep은 기본적으로 POSIX 정규식을 실행함)이라는 점을 지적해야 합니다.

나는 정규식이 무엇인지와 grep 명령에서의 기본 사용법만 알고 있습니다. 그래서 저는 이 세 가지 의견 중 어느 것도 받을 수 없으며 다음과 같은 질문이 마음 속에 있습니다.

  • 사용상의 차이점은 무엇입니까?.*?그리고.*?
  • 어떤 상황에서 어느 것이 더 낫습니까? 예를 들어주세요.

누군가가 이 댓글을 이해할 수 있다면 도움이 될 것입니다.


업데이트: 질문에 대한 답변정규식은 Shell Globs와 어떻게 다릅니까? @쿠살라난다만약에이 링크그의 댓글에서.

참고: 필요한 경우 읽어보세요.이 질문에 대한 나의 대답답변하기 전에 문맥을 참조하세요.

답변1

다음과 같은 문자열을 사용한다고 가정해 보겠습니다.

can cats eat plants?

탐욕 연산자를 사용 c.*s하면 로 시작 c하고 끝나는 전체 문자열과 일치합니다 s. 탐욕 연산자는 s가 마지막으로 나타날 때까지 계속 일치합니다.

게으름을 사용하면 문자열이 처음 나타날 c.*?s때까지만 일치합니다 .scan cats

위의 예를 통해 다음과 같은 결론을 내릴 수 있습니다.

"Greedy"는 가능한 가장 긴 문자열과 일치하는 것을 의미합니다. "Lazy"는 가능한 가장 짧은 문자열과 일치하는 것을 의미합니다. ?수량자(예 *: +, ?또는 ) 에 a를 추가하면 {n,m}수량자가 비활성화됩니다.

답변2

Ashok이 지적했습니다..*그래서 .*?몇 가지 추가 정보를 제공하겠습니다.

grep(GNU 버전이라고 가정) 4가지 문자열 일치 방법을 지원합니다.

  • -F옵션이 있는 고정 문자열
  • 기본 정규식(BRE), 기본값
  • -E옵션이 있는 확장 정규식(ERE)
  • -PGNU grep의 옵션이 있는 Perl 호환 정규식(PCRE)

grep기본적으로 BRE가 사용됩니다.

BRE와 ERE는 다음과 같이 기록됩니다.일반적인 표현POSIX 및 PCRE에 대한 장은 다음 문서에 문서화되어 있습니다.공식 웹 사이트. 기능과 구문은 구현마다 다를 수 있습니다.

BRE나 ERE 모두 지원하지 않는다는 점은 언급할 가치가 있습니다.게으른:

여러 개의 인접한 반복 기호("+", "*", "?" 및 공백)의 동작은 정의되지 않은 결과를 생성합니다.

따라서 해당 기능을 사용하려면 PCRE를 사용해야 합니다.

# PCRE greedy
$ grep -P -o 'c.*s' <<< 'can cats eat plants?'
can cats eat plants

# PCRE lazy
$ grep -P -o 'c.*?s' <<< 'can cats eat plants?'
can cats

설명해주실 수 있나요?.*그리고.*??

  • .*가능한 "가장 긴" 1 패턴을 일치시키는 데 사용됩니다 .

  • .*?가능한 "가장 짧은" 1 패턴을 일치시키는 데 사용됩니다 .

내 경험상 가장 바람직한 행동은 대개 두 번째 행동이다.

예를 들어, 다음 문자열이 있고 그 사이의 내용이 아닌 html 태그 2 만 일치시키려고 한다고 가정해 보겠습니다.

<title>My webpage title</title>

이제 .*비교해보세요 .*?:

# Greedy
$ grep -P -o '<.*>' <<< '<title>My webpage title</title>'
<title>My webpage title</title>

# Lazy
$ grep -P -o '<.*?>' <<< '<title>My webpage title</title>'
<title>
</title>

1. 정규식의 맥락에서 "가장 긴"과 "가장 짧은"의 의미는 약간 까다롭습니다.쿠사로난다가 지적했듯이. 자세한 내용은 공식 문서를 참조하세요.
2.HTML을 구문 분석하기 위해 정규식을 사용하는 것은 권장되지 않습니다.. 이는 교육 목적으로만 사용되는 예시이므로 프로덕션에서는 사용하지 마세요.

답변3

문자열은 다양한 방법으로 일치될 수 있습니다(간단한 것부터 더 복잡한 것까지):

  1. 정적 문자열(var='Hello World!'라고 가정):

    [ "$var" = "Hello World!" ] && echo yes
    echo "$var" | grep -F "Hello"
    grep -F "Hello" <<<"$var"

  2. 구체로서:

    echo ./* # 목록모두pwd의 파일.
    case $var in (*Worl*) echo yes;; (*) echo no;; esac
    [[ "$var" == *"Worl"* ]] && echo yes

    기본 및 확장 글로브가 있습니다. 이 case예에서는 기본 glob을 사용합니다. bash [[예제에서는 확장된 glob을 사용합니다. 첫 번째 파일 일치는 기본이거나 extglobbash의 설정 과 같은 일부 셸의 확장일 수 있습니다 . 이 경우 둘 다 동일합니다. Grep은 글로브를 사용할 수 없습니다.

    별표전반적인 상황별표와 다른 의미정규식:

    * matches any number (including none) of모든 문자.
    * matches any number (including none) of the이전 요소.

  3. 기본 정규 표현식(BRE):

    echo "$var" | sed 's/W.*d//' # 인쇄: 안녕하세요!
    grep -o 'W.*d' <<<"$var" #세상을인쇄하다!

    (기본) 쉘 또는 awk에는 BRE가 없습니다.

  4. 확장 정규식(ERE):

    [[ "$var" =~ (H.*l) ]] # 콘테스트: Hello World
    echo "$var" | sed -E 's/(d|o)//g' # print: 지옥이 포효한다!
    awk '/W.*d/{print $1}' <<<"$var" # 인쇄: 안녕하세요
    grep -oE 'H.*l' <<<"$var" # 인쇄: 안녕하세요, 세계

  5. Perl 호환 정규 표현식:

    grep -oP 'H.*?l # 인쇄: 헐

PCRE에서만 a에는 *?특정한 문법적 의미가 있습니다.
별표를 게으르게 만듭니다(욕심이 많지 않음).탐욕을 게으름으로 바꾸세요.

$ grep -oP 'e.*l' <<<"$var"
ello Worl

$ grep -oP 'e.*?l' <<<"$var"
el

이것은 빙산의 일각에 불과합니다.탐욕, 게으름, 그리고유순하거나 소유욕이 강하다. 게다가앞을 보고 뒤를 돌아보세요그러나 이는 별표에는 적용되지 않습니다 *.

탐욕스럽지 않은 정규식과 동일한 효과를 얻는 대안이 있습니다.

$ grep -o 'e[^o]*o' <<<"$var"
ello

아이디어는 매우 간단합니다. dot 을 사용하지 말고 .일치하는 다음 문자를 무효화하세요 [^o]. 네트워크 태그 사용:

$ grep -o '<[^>]*>' <<<'<script type="text/javascript">document.write(5 + 6);</script>'
<script type="text/javascript">
</script>

위의 내용은 @Bob 3의 모든 의견을 완전히 명확하게 합니다. 정의:

  • .*는 glob이 아닌 일반적인 정규식입니다.
  • 정규식만 PCRE와 호환됩니다.
  • PCRE에서: ?Modify* 수량자. .*그것은 탐욕이 아닙니다 .*?.

질문

  • 사용법의 차이점은 무엇입니까?? 그리고.?

    • A는 .*?PCRE 구문에서만 유효합니다.
    • A는 .*휴대성이 더 좋습니다.
    • 포인트를 음수 문자 범위로 바꾸면 탐욕스럽지 않은 일치와 동일한 효과를 얻을 수 있습니다.[^a]*
  • 어떤 상황에서 어느 것이 더 낫습니까? 예를 들어주세요.
    더 나은 것? 목표에 따라 다릅니다. 더 좋은 것은 없으며 각각 다른 목적을 가지고 있습니다. 위에 몇 가지 예를 제시했습니다. 더 필요하세요?

관련 정보