나는 출력을 잡는 동안 사용되는 정규 표현식의 종류와 관련된 SuperUser 에 대해이 질문에 대답 했습니다 .
내가 준 대답은 다음과 같습니다.
tail -f log | grep "some_string.*some_string"
그런 다음 @Bob 이 내 대답에 대한 세 가지 의견으로 다음과 같이 썼습니다.
.*
탐욕스럽고 원하는 것보다 더 많이 캡처 할 수 있습니다..*?
일반적으로 더 좋습니다.
그런 다음
은
?
에 대한 수정 자*
이므로 욕심 많은 기본값 대신 게으르게 만듭니다. PCRE를 가정합니다.
나는을 검색 PCRE
했지만 내 대답에서 이것의 중요성을 알 수 없었습니까?
그리고 마지막으로
또한 이것이 쉘 glob이 아닌 정규식 (기본적으로 POSIX 정규식을 수행하는 grep)임을 지적해야합니다.
grep 명령에서 정규식이 무엇인지, 기본 사용법 만 알고 있습니다. 그래서, 나는 그 3 가지 의견을 얻을 수 없었으며 다음과 같은 질문을 염두에 두었습니다.
- 의 사용의 차이 무엇입니까
.*?
대는.*
? - 어느 것이 더 좋고 어떤 상황에서? 예를 제공하십시오.
또한 의견을 이해하는 것이 도움이 될 것입니다.
업데이트 : 질문에 대한 답변으로 Regex는 Shell Glob과 어떻게 다릅니 까? @Kusalananda 는 그의 의견 에이 링크 를 제공 했습니다 .
참고 : 필요한 경우 문맥을 참조하기 위해 대답하기 전에이 질문에 대한 나의 대답을 읽으십시오 .
답변
Ashok는 이미.*
와 의 차이점을 지적.*?
했으므로 추가 정보를 제공하겠습니다.
grep
(GNU 버전으로 가정) 문자열을 일치시키는 4 가지 방법을 지원합니다.
- 고정 문자열
- 기본 정규 표현식 (BRE)
- 확장 정규식 (ERE)
- Perl 호환 정규 표현식 (PCRE)
grep
기본적으로 BRE를 사용합니다.
BRE 및 ERE는 POSIX 의 정규식 장에 설명되어 있으며 PCRE는 공식 웹 사이트에 설명되어 있습니다 . 기능과 구문은 구현마다 다를 수 있습니다.
BRE 나 ERE가 게으름을 지원하지 않는다는 것은 가치가 있습니다 .
인접한 여러 중복 기호 ( ‘+’, ‘*’, ‘?’및 간격)의 동작은 정의되지 않은 결과를 생성합니다.
따라서 해당 기능을 사용하려면 대신 PCRE를 사용해야합니다.
# BRE greedy
$ grep -o 'c.*s' <<< 'can cats eat plants?'
can cats eat plants
# BRE lazy
$ grep -o 'c.*\?s' <<< 'can cats eat plants?'
can cats eat plants
# ERE greedy
$ grep -E -o 'c.*s' <<< 'can cats eat plants?'
can cats eat plants
# ERE lazy
$ grep -E -o 'c.*?s' <<< 'can cats eat plants?'
can cats eat plants
# 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
.*
vs 에 대해 조금 설명해 주.*?
시겠습니까?
-
.*
“가장 긴” 1 패턴 을 일치시키는 데 사용됩니다 . -
.*?
“가장 짧은” 1 패턴 을 일치시키는 데 사용됩니다 .
내 경험상 가장 원하는 행동은 대개 두 번째입니다.
예를 들어, 다음과 같은 문자열이 있고 html 태그 2 만 일치 시키려고 하지만 그 사이의 내용이 아니라고 가정합니다.
<title>My webpage title</title>
이제 .*
vs를 비교하십시오 .*?
.
# 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. Kusalananda가 지적했듯이 정규식 문맥에서 “가장 길다”와 “가장 짧다”의 의미는 약간 까다 롭습니다 . 자세한 내용은 공식 문서를 참조하십시오.
2. 정규식으로 HTML을 구문 분석하지 않는 것이 좋습니다 . 이것은 교육 목적의 예일 뿐이며 프로덕션 환경에서는 사용하지 마십시오.
답변
다음과 같은 문자열을 사용한다고 가정 해보십시오.
can cats eat plants?
욕심쟁이 c.*s
를 사용하면으로 시작 c
하고 끝나기 때문에 전체 문자열과 일치 s
하며 욕심쟁이 연산자는 s가 마지막으로 나타날 때까지 계속 일치합니다.
반면에 lazy c.*?s
를 사용하는 것은 첫 번째 발생 s
이 발견 될 때까지만 일치합니다 ( 예 : string) can cats
.
위의 예에서 다음을 수집 할 수 있습니다.
“Greedy”는 가능한 가장 긴 문자열을 일치시키는 것을 의미합니다. “게으른”은 가능한 가장 짧은 문자열을 일치시키는 것을 의미합니다. 추가 ?
와 같은 정량에 *
, +
, ?
, 또는 {n,m}
차종이 게으른.
답변
문자열은 여러 가지 방법으로 간단하게 일치시킬 수 있습니다.
-
정적 문자열로서 (var = ‘Hello World!’라고 가정) :
쉘
[ "$var" = "Hello World!" ] && echo yes
그렙echo "$var" | grep -F "Hello"
배쉬grep -F "Hello" <<<"$var"
-
글로브로서 :
shell
echo ./*
# pwd에있는 모든 파일을 나열 합니다 .
쉘case $var in (*Worl*) echo yes;; (*) echo no;; esac
배쉬[[ "$var" == *"Worl"* ]] && echo yes
기본 및 확장 글로브가 있습니다. 이
case
예제는 기본 globs를 사용합니다. bash[[
예제는 확장 globs를 사용합니다. 첫 번째 파일 일치는extglob
bash의 설정과 같은 일부 쉘에서 기본이거나 확장 될 수 있습니다 . 이 경우 둘 다 동일합니다. 그렙은 글로브를 사용할 수 없습니다.A의 별표 글로브는 A의 별표에 비해 뭔가 다른 의미 정규식 :
* matches any number (including none) of
모든 캐릭터를 잡아라 .
정규식* matches any number (including none) of the
선행 요소 . -
기본 정규 표현식 (BRE)으로 :
sed
echo "$var" | sed 's/W.*d//'
# print : 안녕하세요!
grepgrep -o 'W.*d' <<<"$var"
# print World!
(기본) 쉘 또는 awk에는 BRE가 없습니다.
-
확장 정규식 (ERE) :
bash
[[ "$var" =~ (H.*l) ]]
# match : Hello Worl
sedecho "$var" | sed -E 's/(d|o)//g'
# print : Hell Wrl!
awkawk '/W.*d/{print $1}' <<<"$var"
# print : 안녕하세요
grepgrep -oE 'H.*l' <<<"$var"
# print : Hello Worl
-
Perl 호환 정규식 :
grep
grep -oP 'H.*?l
# print : Hel
PCRE에서만 a *?
특정 구문 의미를 갖습니다.
별표가 게으르다 (배고프다) : 탐욕 대신 게으름 .
$ grep -oP 'e.*l' <<<"$var"
ello Worl
$ grep -oP 'e.*?l' <<<"$var"
el
이것은 빙산의 일각이다,있다 , 욕심 게으른 하고 유순 또는 possesive . 또한 미리보기와 뒤로보기가 있지만 별표에는 적용되지 않습니다 *
.
욕심없는 정규 표현식과 동일한 효과를 얻는 대안이 있습니다.
$ grep -o 'e[^o]*o' <<<"$var"
ello
아이디어는 매우 간단합니다. 점을 사용하지 말고 .
다음 문자를 무시하여 일치 시키십시오 [^o]
. 웹 태그로 :
$ grep -o '<[^>]*>' <<<'<script type="text/javascript">document.write(5 + 6);</script>'
<script type="text/javascript">
</script>
위의 내용은 모든 @Bob 3 의견을 완전히 명시해야합니다. 역설 :
- . *는 일반적인 정규 표현식이며 글로브가 아닙니다.
- 정규식 만 PCRE와 호환 될 수 있습니다.
- PCRE에서 😕 * 수량자를 수정하십시오.
.*
욕심.*?
이 아닙니다.
질문
-
의 사용법에 어떤 차이가 있습니까? ? vs. ?
- A
.*?
는 PCRE 구문에서만 유효합니다. - A
.*
는 더 휴대하기 편리합니다. - 점을 부정 문자 범위로 바꾸면 욕심없는 일치와 같은 효과를 얻을 수 있습니다.
[^a]*
- A
-
어느 것이 더 좋고 어떤 상황에서? 예를 제공하십시오.
보다 나은? 목표에 달려 있습니다. 더 나은 것은 없으며, 각각 다른 목적으로 유용합니다. 위의 몇 가지 예를 제공했습니다. 더 필요하십니까?