[완료]정규식에서 특정 단어 제외하는 건 불가능 하나요?

문성훈의 이미지

예를 들면 이런게 하고 싶습니다.

abcd^(abcd)abcd;

즉 abcd 로 둘러쌓인 문장을 찾고 싶은데요. 단 그 중간에 또 다른 abcd가 있으면 안되는 거예요.

'[^']' 과 같은 건데 '를 abcd로 대신한거라 보시면 되구요.

지금 두시간째 구글에서 찾아보다가 gg 치고 여쭤봅니다. ^^;;;

가르침을 주세요~ ^^

develog의 이미지

[^ab] a 혹은 b를 제외한 모든 문자와 매치
[] 안에서 ^는 부정을 의미합니다.

성훈의 이미지

그러니까 문자열을 제외하고 싶다는 말이었습니다.

제가 제대로 표현을 못했나 보네요. ^^;;;

^는 문자단위로 제외하는 거라서요.

성훈의 이미지

이제 보니 글이 잘 못올라왔군요. ㅜㅜ

다시 질문 드리겠습니다.

abcd라는 문자열로 둘러 쌓인 문자열을 찾고 싶습니다.

abcd~~~fkngfngs~~~~abcd 이런 거요.

근데 ~~~~안에는 abcd라는 문자열이 없어야해요.

그러니까 abcd^[abcd]+abcd 같은 건데

^[]는 한 문자 단위에 적용되는 거라서요. 문자열 단위로 쓸 수 있는 방법이 있을까요?

aero의 이미지

Perlmania 게시판
http://www.perlmania.or.kr/bbs/bbs.html?mode=list&table=lang
에 가보시면 맨위에 님과 똑같은 질문과 그에 대한 답변들이 있습니다.

송효진의 이미지

저 게시판의 내용은 정규식으로 할만한 내용이고,
윗분의 질문은 못할것 같군요.

asdf(asdf제외)asdf -> asdfovaijwoeijfoasjdlfjasdf 와
asdf(asdf나오면 끝) -> asdf 는 다른거죠.

emerge money

wkpark의 이미지

preg_match('/(abcd)((?:(?!abcd))*)\1/',$str,$match); // => 1차시도

preg_match('/(abcd)((?:(?!abcd))*|.*)\1/U',$str,$match); // => 2차시도

이정도 ? 확인은 제대로 안해봤습니다. $match[2]가 원하시는 것입니다.

온갖 참된 삶은 만남이다 --Martin Buber

송효진의 이미지

1번은 안되고요.
2번은 /(abcd)(.*)\1/U 와 동일하고 동작합니다.

근데 U 가 근본적인 해결은 못되는게 abcd.*abcd 사이에 qwer 을 제외하고자 할 때는 또 난감하거든요.

(?!abcd) 가 제기능을 못하는 이유는 문자열 길이가 고정되지 않았기 때문입니다.
그러니까 aabcd 부터 시작한다면 aabc 는 abcd 가 아니기 때문에 통과
그 뒤는 d 부터... < 가 없어서 아닌가...

헷갈리는데 어쨌든
? 연산이 되려면 비교식에 문자길이를 고정시킬 필요가 있습니다.

emerge money

wkpark의 이미지

> 2번은 /(abcd)(.*)\1/U 와 동일하고 동작합니다.

네 먼저 이걸 생각했다가, 이걸 고쳐본 것입니다.

> 근데 U 가 근본적인 해결은 못되는게 abcd.*abcd 사이에 qwer 을 제외하고자 할 때는 또 난감하거든
요.

그렇겠군요.

> (?!abcd) 가 제기능을 못하는 이유는 문자열 길이가 고정되지 않았기 때문입니다.
> 그러니까 aabcd 부터 시작한다면 aabc 는 abcd 가 아니기 때문에 통과
> 그 뒤는 d 부터...

그렇다면 이건 어떤가요?

preg_match('/(abcd)((?:(?:(?!abcd))|.)*)\1/U',$str,$match);

온갖 참된 삶은 만남이다 --Martin Buber

송효진의 이미지

|. 이 들어있는 이상 .* 와 다를바가 없습니다.^^;

emerge money

ibin의 이미지

제외 조건시 문자 하나가 아닌 단어 단위는 역시 안되는건가요?

저도 단어 단위로 제외 조건을 설정해보려고 찾아봤었는데 아직 발견하지 못했습니다.

juneaftn의 이미지

Python으로 해봤습니다. 다른 언어로 옮기는 데에 별 어려움이 없을 겁니다.

>>> def resub(p,s,flags=None):
    return re.sub(p,r'{\g<0>}',s)
>>> resub('pattern','find this pattern!')
'find this {pattern}!'
>>> resub("abc([^a]|a[^b]|ab[^c])*abc","abcabdabc abcabc abclmnr")
'{abcabdabc} {abcabc} abclmnr'
>>> def anybut(l):
    p = '';opt = []
    for each in l:
        opt.append(p + '[^' + each + ']')
        p += each
    return '(' + '|'.join(opt) + ')*'
>>> resub('abcd'+anybut('abcd')+'abcd','abcdhello world abcd gogogo abcd find me abcd')
'{abcdhello world abcd} gogogo {abcd find me abcd}'

non-greedy search가 지원된다면 다음과 같이도 가능합니다.
>>> resub('abcd(.*?)abcd','abcdhello world abcd gogogo abcd find me abcd')
'{abcdhello world abcd} gogogo {abcd find me abcd}'
esrevinu의 이미지

>>> resub("abc([^a]|a[^b]|ab[^c])*abc","abcaaabc")
'{abcaaabc}'
>>> resub("abc([^a]|a[^b]|ab[^c])*abc","abcacaabc")
'abcacaabc'

안 되는 것 맞죠?

--
foldl (flip (:)) [] "universe"

juneaftn의 이미지

ab로 둘러쌓인 문자열의 예

>>> resub('ab[^a]*(a[^ab][^a]*)*aa*b',"abbaab abxxxbab abab abaab")
'{abbaab} {abxxxbab} {abab} {abaab}'

alee의 이미지

단어단위로 매칭이 안 된다면 일단 abcd를 한 문자로 치환한 다음 매칭 조건을 쓰시고 다시 원래대로
치환하는 방법도 있습니다. 그러자면 치환하는 데에 사용할 문자가 원래 문서에 들어 있지 않도록
해줘야 하는데, 사용할 문자를 적당히 원래 문서에 없는 문자열로 바꿔주면 됩니다.

예를 들어서 원래 문서에 _space_ 이런 문자열이 하나도 없다면 빈칸을 전부 _space_로 바꾸고
그 다음에 abcd를 전부 빈칸으로 치환한 다음 스페이스 문자를 사용해 매칭 컨디션을 씁니다.
그런 다음 다시 빈칸을 abcd로 바꾸고 _space_를 빈칸으로 바꿔주면 원하는 작업을 마칠 수
있습니다.

더 좋은 방법은 빈칸을 _space_로 바꾸고 스페이스 문자를 사용하는 대신 처음부터 문서에 안 들어
있는 문자를 사용하는 것입니다. 예를 들면 “·”, “※” 등을 사용하면 됩니다. 세벌식을 사용하면
이런 여분의 문자가 키보드로 바로 입력 가능하기 때문에 무척 편리합니다. ㅡㅡ;

좀 무식한 방법이기는 하지만 에디터 내에서 바로 해결이 가능하니까 편집하고 있는 문서 용량이
그리 크지 않다면 그럭저럭 쓸만합니다. 아, 그러고 보니 파일 편집에 사용하려고 하시는건지
아니면 프로그램 내에서 사용하려고 하시는건지 안 적으셨네요.

송효진의 이미지

제가 저런게 필요한 경우가 많기 때문에 한번에 할 수 있는 방법이 간절히 필요합니다. :q

테이블이 많이 있고, 내용만 긁고자 할 때 제목칸만 제외하기 같은거요.

preg_match_all 로 <td([^>]*)>(.*?)</td> 하고,
for 루프를 돌려서 \1 에 class="title" 있는것만 제거하는데
왜이리 루프가 꼴보기 싫은지... ::evil::

emerge money

puaxx의 이미지

preg_replace_callback 함수는 어떨까요?

송효진의 이미지

치환이 아니고 제목을 제외 하는것입니다.^^

emerge money

wkpark의 이미지

juneaftn님이 언급하신 방법을 써놓은 곳이 있군요

http://www.php.net/manual/en/ref.regex.php#19254

alee님의 방법을 쓴다거나

온갖 참된 삶은 만남이다 --Martin Buber

esrevinu의 이미지

abcd에 둘러싸인 문자열을 찾으면 되는 거 아닌가요? minimal matching(?)으로 아래와 같이... 제가 문제를 잘못 이해했나요?

#!/usr/bin/perl -w
 
use strict;
 
$_ = "123abcdabcabcddddabcaaaabcd123abcd";
 
while (/abcd(.*?)(abcd.*)/) {
  print "$1\n";
  $_ = $2;
}

--
foldl (flip (:)) [] "universe"

익명사용자의 이미지

저 위에 보시면 이미 비슷한 해결책은 다 나왔습니다. 거시서 더 발전해서 일반적인 얘길 하려고 하는것이고요.
이 글타래 제목에 대한

seoleda의 이미지

제 생각에는 정규표현식 만으로는 위의 문제를 해결하기 못할 것 같습니다.
정규표현식이라 하면 type 3 grammer (regular grammars)로 표현되는 문자열을 말합니다. 정규 표현식을 대충 살펴보면, a와 b 가 정규표현이면 ab, [ab], a* 로 표현되는 식을 의미합니다. 그런데 위의 문제는 abcd로 싸인 문자열 이고 중간에는 abcd가 없어야 한다고 하니, 정규문법을 찾기가 어려울 듯 합니다.
다만, context free grammer에는 속하는 것으로 보이기 때문에 기타 컴파일러나 인터프리터의 도움을 받아서 해결 할 수는 있을 것입니다.
정규표현식 만으로 저 문제를 표현할 수 있는 분이 계시다면 100원 드리겠습니다. ^^

익명사용자의 이미지

약간의 transformation만 하면 되는데...

seoleda의 이미지

그냥, 약간의 트랜스폼만 하면 됀다고 하니 100원을 드리기가 좀 난감합니다.
생성 규칙을 알려 주시고, 그 생성규칙이 정규문법임을 증명하시면 드리겠습니다. 문법을 게시판에 올려주시면 다른 사람들에게도 많은 도움이 될것 같습니다.

익명사용자의 이미지

위에 이미 언급된 juneaftn님의 방법이 한가지 방법입니다.

seoleda의 이미지

1) 특정 문자열을 포함하지 않는 생성규칙과,
2) 2-1) 특정문자열을 포함하지 않으면서
2-2) 그 문자열이 앞 뒤에 나와야 하는 생성규칙은
다릅니다.

특정 문자열을 포함하지 않는 생성규칙은 juneaftn님이나, 아래에 언급된 방법을 통해서 해결이 가능합니다.
그러나, 2)는 앞서도 얘기 했지만, 제 판단으로는 정규문법처럼 보이지 않습니다.

정규문법이라 함은 다음과 같은 우선형문법 (right linear grammer) 이나 좌선형문법 (left linear grammer) 중 하나로만 표현되어야 합니다. (대문자는 논터미널이라고 하며, 소문자는 그냥 문자라고 이해하세요. 자세한 내용은 컴파일러론 등을 찾아보시길..)
A -> tB|t (우선형문법)
A -> Bt|t (좌선형문법)

그럼 다시 문제로 돌아와서 생성규칙을 쉽게 만들 수 있도록 문제를 좀 간략하게 해봅시다.
알파벳은 a,b,c 3종류만 있다고 하고, 문자 'a'를 포함하지 않으면서, 처음과 끝이 a인 문법을 만들면 다음과 같은 2가지의 생성규칙이 필요합니다.

생성규칙1) S -> aAa
생성규칙2) A -> bA|cA

여기서 생성규칙을 잘 살펴보면 1)은 좌선형도 우선형 문법도 아닙니다. 1)을 분해해서 좌선형 혹은 우선형 문법으로만 표시할 수 있다면 정규문법만으로도 위와 같은 문제를 해결 할 수 있습니다만, 1)과 같은 형태를 한가지 형태의 문법으로 표현한 예는 보지 못했습니다. (제가 컴파일러에 문외한이라서 혹시 보신 분이 계시면 알려주세요. 500원 드리겠습니다 ㅋㅋ)
다행이 1과 같은 문법은 context free grammer에는 해당하므로, 스택 비스무리한 구조를 이용한다던지, 대부분의 프로그래밍언어가 CFG에 해당하므로 약간의 코드를 추가하여 문제를 해결 할 수 있습니다.

"특정 문자열을 포함하지 않는"에 해당하는 정규 표현식은 잘 보았습니다만, 그것만으로 문제를 해결했다고 보긴 어렵네요. 익명님께서 반은 해결하셨다고 판단되므로 쪽지를 주시면 50원은 보내드리겠습니다.

익명사용자의 이미지

with N = {S, A, B}, Σ = {a, b, c}, P consists of the following rules:

* S -> a A
* A -> b A
* A -> c A
* A -> a B
* B -> ε

Expanding this single-character case into a multiple-charaters problem is left as an exercise for the reader.

seoleda의 이미지

제가 못한다고 다른사람도 못하는건 아니군요.
하마터면 선무당이 사람잡을 뻔 했습니다.
600원 드리겠습니다. 쪽지를...

mithrandir의 이미지

/abcd([^a]...|.[^b]..|..[^c].|...[^d]|.{1,3}|.{5,})abcd/

쓸데없이 길어지지만 가능하긴 합니다. 저걸 직접쓰기보다는 생성해주는 방법을 써도 되겠지요.

하지만 정규표현식으로만 처리할게 아니라면..
/abcd(.*?)abcd/
로 모든 매치된 문자열을 찾아서 abcd가 아닌것만 걸러내는게 더 나아보입니다. 물론 저걸 치환할 생각이라면 곤란하겠군요.

언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net

esrevinu의 이미지

안 되는데... 안 되나 봅니다.

>>> resub('abcd([^a]...|.[^b]..|..[^c].|...[^d]|.{1,3}|.{5,})abcd',"abcdabcdefabcd")
'{abcdabcdefabcd}'

--
foldl (flip (:)) [] "universe"

mithrandir의 이미지

In [8]: p = re.compile('abcd([^a]...|.[^b]..|..[^c].|...[^d]|.|..|...|.....+)abcd')
 
In [12]: p.match("abcdabcdefabcd")
Out[12]: <_sre.SRE_Match object at 0xb7ca79e0>
 
In [13]: p.match("abcdabcdabcd")
 
In [14]: p.match("abcdabcdeabcd")
Out[14]: <_sre.SRE_Match object at 0xb78e3aa0>

파이썬 정규표현식에서는 {}를 지원하지 않는 것 같습니다.

참고로 루비에서는

irb(main):001:0> /abcd([^a]...|.[^b]..|..[^c].|...[^d]|.{1,3}|.{5,})abcd/ =~ "abcdabcdeabcd"
=> 0
irb(main):002:0> $1
=> "abcde"
irb(main):003:0> /abcd([^a]...|.[^b]..|..[^c].|...[^d]|.{1,3}|.{5,})abcd/ =~ "abcdabcdabcd"
=> nil

언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net

jo1413의 이미지

abcd[^(abcd)]abcd
이렇게 하면 될 것 같습니다.
[] 안에 ^는 부정의 뜻이고 ()로 abcd를 찾으면 안된다.

^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
이걸 보고 웃는 모습이라고 생각이 되신다면 이모티콘 사용에 중독 되신 겁니다..
Get busy living, or get busy dying.
내가 제일 좋아하는 소설 동천~♥ http://cafe.daum.net/awintersky

------------------------------------------------------------
Get busy living, or get busy dying.

송효진의 이미지

거의 모든 정규식에서 [] 안의 내용은 - 표기를 제외하고는 각각의 문자를 의미합니다.
[^(abcd)] 는 (,a,b,c,d,) 를 부정하는거죠.

emerge money
http://wiki.kldp.org/wiki.php/GentooInstallSimple - 명령어도 몇 개 안돼요~
http://xenosi.de/

jo1413의 이미지

그렇군요.
()로 씌워줘도 []안에서는 각각의 문자를 의미하는군요.

다시 한 번 생각해 보겠습니다.
------------------------------------------------------------
Get busy living, or get busy dying.
내가 제일 좋아하는 소설 동천~♥ http://cafe.daum.net/awintersky

------------------------------------------------------------
Get busy living, or get busy dying.

impactbar의 이미지

오래된 글이네요. 그래도 ^^;

일단 vim 에서는 됩니다.

abcd abcd 로 이루어진 문자열의 최소값을 찾는 문제군요.

abcd.*abcd 는 뉴라인 없는 최대값을 검색하니 안되고

abcd.\{-}abcd 로 검색하시면 abcd.*abcd를 만족하는 최소값으로 검색됩니다.

vim 에서

abcd abcd abcd
abcd 1234 abcd
abcd 1234 aabcd abcd

를 /검색으로 abcd.\{-}abcd 검색해보시면 노랗게 범위가 보입니다.

원하시는게 맞을지 모르겠군요. ^^

송효진의 이미지

아닙니다.
asdf.*?asdf 에서 조건이 하나 더 필요합니다.
qwer 가 없는것만 골라내는게 그거죠.
그런데 정규식으로는 qwer 가 있는건 골라낼 수 있지만 없는건 못합니다.
[^q][^w][^e][^r] 이나 (?!qwer) 같은걸로는 딱 asdfqwerasdf 같은 고정된 문자열에만 해당하죠.

emerge money
http://wiki.kldp.org/wiki.php/GentooInstallSimple - 명령어도 몇 개 안돼요~
http://xenosi.de/

impactbar의 이미지

asdf.*?asdf 라고 쓴게 아니고요 abcd.\{-}abcd 라고 쓴 댓글이었습니다.

조금 오해하신 것 같습니다. vim 에서 동작하는 정규식 입니다. 다른 곳에서는 테스트 못해봤습니다.

발제자의 문의가 abcd ~ abcd 최소 구간을 의미하는 것으로 판단했습니다.

송효진의 이미지

두가지 정규식의 의미가 다르다고 보십니까?
같은겁니다.
vim 용이거나 perl 용이거나 하는 차이만 있습니다.

그 '가장 짧은것을 뽑아오는것' + '사이에 특정 {{문장}} 이 {{안 오도록}}' 하는 것이 주제입니다.
그건 아직 정규식으로는 불가능하죠.

ps.
하도 오래된 글이라 원 주제를 착각했군요. 죄송합니다.
원 주제에 관한건 이미 해결이 났습니다. 말씀하신 가장 짧은것을 뽑는건 다 나왔죠.

emerge money
http://wiki.kldp.org/wiki.php/GentooInstallSimple - 명령어도 몇 개 안돼요~
http://xenosi.de/

bluesky7의 이미지

정규식 검색을 하다 이 글을 보게 되어 한번 생각해 보았습니다.
다음과 같은 표현식으로 하면 될 것 같은데요.
모든 경우의 수에 대해 테스트는 하지 않았지만 잘 되는 것 같습니다.

abcd(a|[^a].*|ab|a[^b].*|abc|ab[^c].*|abc[^d].*)abcd

이게 원하는 게 맞는지 모르겠네요...

맨발의 이미지

정규식에서 단어 제외를 검색 하다가 이까지 흘러왔네요.

정규식에서 단어 제거는.. 안되는건 아니지만 꽤 귀찮군요..!!!

설명 대로라면
ab단어 비포함 => a[^b]|[^a]b|[^a][^b]
10글자 단어라면.. 후덜덜.. @ㅁ@;;;

글을 쭉 보다가 글쓴님의 문제의 경우 다음과 같은 우회책을 생각해 보았습니다.

return preg_replace(/^abcd|abcd$/, '', $subject) != str_replace('abcd', '', preg_replace(/^abcd|abcd$/, '', $subject));

--------------------------------------------
:: 누구보다 빠르게 남들과는 다르게

익명 사용자의 이미지

(?(?=조건글)true값|false값)
이 문법을 쓰면 됩니다.

아래 링크 참조하심 되요.
http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=6076&sca=&sfl=wr_subject&stx=%C1%A4%B1%D4%C7%A5%C7%F6&sop=and&page=2

abcd 제외하려면
abcd((?(?=abcd)[^abcd]|.)*)abcd

dearmai의 이미지

abcd(\\.|^abcd)*abcd

abcd 에 둘러 싸인 문자열을 찾는대신 abcd 사이에 어떤 문자 열이라도 괜찮으나 abcd 는 제외 한다.

익명 사용자의 이미지

Perl에서 해결방법찾다가 여기까지 왔네요.
제 문제는 다음이었습니다.

문자열에서 A[ options ] 라고 쓰여진 부분을 찾는데
options 에 id=12 와 같이 id 값이 있는 경우를 제외하고
만약 있다면 id 값을 options 에 집어넣는 작업을 전체 문자열에 대해서 하고 싶었습니다.
다음과 같이 했더니 되더군요.

while (/A\[(.*?)\]/ and $1 !~ /id=\d/) {
s/A\[$1\]/A\[$1,id=$i\]/;
++$i;
}

익명 사용자의 이미지

strFileAll = "

strFileAll = System.Text.RegularExpressions.Regex.Replace(strFileAll, "^.*[^<]*[^t]*[^a]*[^b]*[^l]*[^e]*
]*>", "");
tag를 파싱하기 위한 소스코드인데요. 기능은 - ...
에 해당하는 내용을 지우기 - 문서에 첫번째로 나오는
tag를 찾기 위해서 앞에 "
목적은
- 순수하게 table contents만을 편하게 하기 위함입니다.

그러나 비추입니다. 아마도 복잡도가 O(n!)일 겁니다. 차라리

tag 기준으로 split을 하셔서 데이타를 가져오는 쪽이 빠릅니다.
해서 최종솔루션은 다음과 같습니다.

string[] strFileAllArray = System.Text.RegularExpressions.Regex.Split(strFileAll, "

]*>|
]*>");
strFileAll = strFileAllArray[1];

정규표현식은 문자 하나 단위로 판단을 바꾸기 때문에 특정 문자를 기준으로 판단을 배제하거나 하는 방법은 없다고 생각합니다.
(사실 저도 엄청 궁금한 문제이긴 한데요.. 수학적으로 증명이 힘드네여..고수님들 중에 정규표현식에서 표현가능한 case 불가능한
case 아시는 분이 계시면 조언부탁드립니다.)
위의 방법처럼 각 문자마다 처음으로 돌아가서 판단하는 방법은 있겠지만 시간이 극단적으로 오래걸리니 Split을 이용하는 것이
옳을 듯합니다.

익명 사용자의 이미지

strFileAll = “

strFileAll = System.Text.RegularExpressions.Regex.Replace(strFileAll, "^.*[^t][^a]*[^b]*[^l]*[^e]*
]*>”, “”);

tag를 파싱하기 위한 소스코드인데요. 기능은
- …
에 해당하는 내용을 지우기
- 문서에 첫번째로 나오는
tag를 찾기 위해서 앞에 “<table” 문자열을 배제해야 했습니다.

목적은
- 순수하게 table contents만을 편하게 하기 위함입니다.

그러나 비추입니다. 아마도 복잡도가 O(n!)일 겁니다. 차라리

tag 기준으로 split을 하셔서 데이타를 가져오는 쪽이 빠릅니다.
해서 최종솔루션은 다음과 같습니다.

string[] strFileAllArray = System.Text.RegularExpressions.Regex.Split(strFileAll, “

]*>|
]*>”);
strFileAll = strFileAllArray1;

정규표현식은 문자 하나 단위로 판단을 바꾸기 때문에 특정 문자를 기준으로 판단을 배제하거나 하는 방법은 없다고 생각합니다.
(사실 저도 엄청 궁금한 문제이긴 한데요.. 수학적으로 증명이 힘드네여..고수님들 중에 정규표현식에서 표현가능한 case 불가능한 case 아시는 분이 계시면 조언부탁드립니다.)
위의 방법처럼 각 문자마다 처음으로 돌아가서 판단하는 방법은 있겠지만 시간이 극단적으로 오래걸리니 Split을 이용하는 것이
옳을 듯합니다.

Prentice의 이미지

Perl이나 Vim 등에서는 pattern matching을 할 때 negative look-ahead, negative look-behind를 할 수 있습니다.

/회피\(율\)\@!/

Vim에서 회피가 들어간 모든 줄을 찾되 회피율은 제외합니다. 이건 좀 단순한 예이지만 더 복잡하게도 가능합니다.

익명 사용자의 이미지

php로 해봤는데..

" "src" 가 아닌것 "\b(?:(?!\bsrc).)*" 을 지나서
src 의 내용 뽑아오기

$str = '';
$pat = '/<\bimg\b(?:(?!\bsrc).)*src\s*=\s*\"?([^\"\>]+)\"?>/i';
preg_match_all($pat, $str, $mat);

결과
http://www.aaa.com/img/aaa.gif

impactlife의 이미지

<img onclick="aaabbb();" src="http://www.aaa.com/img/aaa.gif">

"<img" 로 시작해서 "src 아닌것" 다음 src...

익명 사용자의 이미지

abc라는 단어를 제외
^((?!abc)[\s\S])*$

문채후의 이미지

1. 문제는 abcd와 abcd로 둘러쌓인 구문안의 문자열이 abcd가 포함되어 있으면 안된다

아래와 같이 하시면 됩니다

abcd.*?(?(?=abcd).*?)abcd

문채후의 이미지

참고로 abcd~abcd구문안에 cdef문자열이 포함된 것을 제외하는 구문은 아래와 같습니다

abcd(?(.*(?=cdef)).*(?=cdef)|.*?)abcd

문채후의 이미지

테스트 해보니 c# RegEx에서는 되는 구문인데 PCRE 스펙에는 없나보네요
PCRE 스펙으로 하면 아래와 같이 하면 될 것 같네요
abcd(?!.*?cdef).*?abcd

문채후의 이미지

abcd가 포함되어 있으면 안된다가 아니라;;;
abcd가 포함되어 있는 구문은 제외해야 되네요
이건 어떻게 해야 할지 음......

문채후의 이미지

쉽지는 않네요 -_-;;;
1. abcd로 시작하고 abcd로 끝나는 구문을 매칭
2. abcd~abcd~abcd의 형태는 매칭하지 않음

(^|\s+)abcd((?!abcd).)*?abcd($|\s+)

ㅇㅇ의 이미지

위쪽에 댓글 다 봤는데, 정답이 이거 하나밖에 없는 듯.

abcd(a|[^a].*|ab|a[^b].*|abc|ab[^c].*|abc[^d].*)abcd

익명 사용자의 이미지

12년 전 게시글이 종종 발굴되어 읽히거나 새 댓글이 달리거나 하는 게 kldp의 매력이지요.
그런데 형식언어론(Formal language theory) 측면에서 고찰한 댓글이 여태 없는 것 같은데, 제가 한 번 써 보겠습니다.
뭐 그래봤자 기껏해야 학부 형식언어론 과목 중간고사 수준의 문제이기는 합니다만..

결론부터 정리하면, 주어진 알파벳 Σ, 문자열 s∈Σ*에 대해서 "s로 시작하고, 중간에 s가 포함되지 않으며, s로 끝나는" 문자열들의 집합은 정규 언어(Regular language)가 맞으며, 당연히 대응되는 정규 표현식이 있습니다.

증명:
(1) 일단 문자열 s 하나만을 포함하는 언어 L1는 정규 언어입니다.
(1-1) trivial. 문자열 s이 그대로 대응되는 정규 표현식이 되지요.
(2) s를 포함하지 않는 문자열들의 집합 L2가 정규 언어라는 것을 증명합니다.
(2-1) s를 포함하는 문자열들의 집합 L3이 정규 언어라는 것을 증명합니다.
(2-1-1) .*s.* 이렇게 정규 표현식을 바로 만들 수 있지요.
(2-2) L2는 L3의 여집합입니다. 다시 말해 L2 = Σ* - L3
(2-3) 정규 언어는 complement에 대해 닫혀 있습니다. 즉 L이 정규 언어이면 Σ*-L도 정규 언어입니다.
(2-3-1) 이 증명은 임의의 정규 언어에 대응되는 결정적 유한 상태 기계(DFA)가 존재한다는 사실을 이용합니다.
(2-3-2) 이 DFA는 5-tuple (Q, Σ, δ, q0, F)으로 이루어져 있는데, 여기서 Accept states를 뒤집은 DFA, 즉 (Q, Σ, δ, q0, Q - F)를 생각해서 새 DFA를 만들 수 있습니다.
(2-3-3) 새로 만든 DFA는 이전 DFA가 accept한 모든 문자열을 reject하고, 이전 DFA가 reject한 모든 문자열을 accept합니다.
(2-3-4) 새로 만든 DFA에 대응되는 정규 언어는 이전 언어의 complement가 됩니다. 따라서 임의의 정규 언어의 complement는 정규 언어입니다.
(2-4) 따라서 L2는 정규 언어입니다.
(3) 정규 언어는 concatenation에 대해 닫혀 있습니다.
(3-1) trivial. L1에 대응되는 정규 표현식 r1과 L2에 대응되는 정규 표현식 r2가 있으면, 그 둘을 그냥 이어 붙이면 되죠.
(4) 이제 정규 언어 L1, L2를 L1, L2, L1 순으로 이어 붙이면 최종적으로 우리가 원하는 언어가 나오고, 정규 언어가 concatenation에 대해 닫혀 있으므로 이 언어는 정규 언어입니다.

증명 끝.

여기서 문제는 (2-3)입니다. 이 사실에 대한 증명은 정규 표현식이 아니라 DFA를 가지고 하고 있는데,
그래서 L3은 정규 표현식을 쉽게 찾을 수 있어도, 그걸 가지고 L2의 정규 표현식을 찾으려면 DFA로 한 번 갔다가 와야 하거든요.

근데 DFA가 주어졌을 때 대응되는 정규 표현식을 찾는 알고리즘(Kleene's algorithm)은, 직접 써 보시면 아시겠지만 꽤 간단한 언어에 대해서도 상당히 지저분한 결과가 나옵니다. -_-;; 물론 결과야 정확하겠지만. 수업시간에 배울 때도 그래서 그냥 "이론적으로 변환이 가능하다" 정도로만 다루고 넘어가곤 하지요.

그래서, 이게 이론적으로 되기는 되는데 형식언어론에서 쓰는 최소화된 형태의 정규표현식으로는 진짜 까마득하고, 각 언어별 정규 표현식 확장 기능을 쓰면 좀 더 쉽게 할 방법이 있을겁니다. 많은 분들이 시도해 보셨고요.

익명 사용자의 이미지

abcd((?!abcd).)*abcd

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.