2011-02-07 55 views
7

Tôi đang làm một số thể dục biểu hiện chính quy. Tôi đặt bản thân mình nhiệm vụ cố gắng tìm kiếm mã C# nơi có một cách sử dụng toán tử không theo sau bởi một kiểm tra rỗng trong một khoảng không gian hợp lý. Bây giờ tôi không muốn phân tích mã C#. Ví dụ. Tôi muốn chụp các đoạn mã nhưBiểu thức chính quy tiêu cực lookahead

var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1.a == y1.a) 

Tuy nhiên, không nắm bắt

var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1 == null) 

cũng không cho rằng vấn đề

var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(somethingunrelated == null) {...} 
    if(x1.a == y1.a) 

Như vậy bất kỳ ngẫu nhiên null-kiểm tra sẽ được tính như là một "kiểm tra tốt "và do đó không tìm thấy.

Câu hỏi đặt ra là: Làm cách nào để tôi khớp thứ gì đó trong khi đảm bảo không tìm thấy thứ gì đó khác trong nền đất của nó.

Tôi đã thử cách tiếp cận ngây thơ, tìm kiếm 'dưới dạng' rồi thực hiện một cái nhìn tiêu cực trong vòng 150 ký tự.

\bas\b.{1,150}(?!\b==\s*null\b) 

Biểu thức chính quy ở trên phù hợp với tất cả các ví dụ trên. Ruột của tôi nói với tôi, vấn đề là nhìn về phía trước và sau đó làm tiêu cực lookahead có thể tìm thấy nhiều tình huống mà lookahead không tìm thấy '== null'.

Nếu tôi thử phủ nhận toàn bộ biểu thức, thì điều đó cũng không giúp ích gì, tại thời điểm đó sẽ khớp với hầu hết mã C# xung quanh.

+2

Bạn không thể sử dụng trình phân tích cú pháp C# thích hợp? – Gumbo

+2

Tôi đã nói ngay từ đầu "Tôi đang tập thể dục thể dục thường xuyên. Tôi tự đặt mình vào nhiệm vụ tìm kiếm C#" ... –

+0

Đây có phải là xem bóng đá và suy nghĩ "nó giống như thể dục dụng cụ"? :-) – xanatos

Trả lời

11

I yêu thích regex thể dục dụng cụ! Đây là một PHP regex nhận xét:

$re = '/# Find all AS, (but not preceding a XX == null). 
    \bas\b    # Match "as" 
    (?=     # But only if... 
     (?:    # there exist from 1-150 
     [\S\s]   # chars, each of which 
     (?!==\s*null) # are NOT preceding "=NULL" 
    ){1,150}?   # (and do this lazily) 
     (?:    # We are done when either 
     (?=    # we have reached 
      ==\s*(?!null) # a non NULL conditional 
     )    # 
     | $    # or the end of string. 
    ) 
    )/ix' 

Và ở đây nó là trong Javascript phong cách:

re = /\bas\b(?=(?:[\S\s](?!==\s*null)){1,150}?(?:(?===\s*(?!null))|$))/ig; 

Cái này đã làm cho đầu tôi đau một chút ...

đây là dữ liệu thử nghiệm tôi đang sử dụng:

text = r""" var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1.a == y1.a) 

however, not capture 
    var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1 == null) 

nor for that matter 
    var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(somethingunrelated == null) {...} 
    if(x1.a == y1.a)""" 
+0

Và nếu bạn muốn nó hoạt động với thử nghiệm có điều kiện tiêu cực, ví dụ: 'X! = Null', chỉ cần thay đổi mỗi:' == 'thành:' [! =] = ' – ridgerunner

+0

Rất dễ thực hiện và giải thích tốt. +1. Tôi muốn bao gồm các thông báo trước về regex không được 100% đáng tin cậy để phân tích cú pháp C#, mặc dù. –

2

Đặt .{1,150} bên trong bảng điều khiển và thay thế . bằng \s\S (nói chung, . không khớp với dòng mới). Ngoài ra, \b có thể gây hiểu lầm gần ==.

\bas\b(?![\s\S]{1,150}==\s*null\b) 
+0

Tôi không thể làm cho ý tưởng của bạn hoạt động, nó vẫn bao gồm ví dụ thứ hai ở trên trong kết quả tìm kiếm của tôi. –

+0

Regex này: '\ bas \ b (?! [\ S \ S] {1,150} == \ s * null \ b)' khá gần, nhưng không khớp với AS thứ hai trong tập đầu tiên của "nên khớp "dữ liệu thử nghiệm. – ridgerunner

+0

@ridgerunner có hoạt động với bạn bằng Python không? Tôi không có thiết lập C# để kiểm tra. – robert

2

Tôi nghĩ rằng nó sẽ giúp đặt tên biến vào() để bạn có thể sử dụng nó làm tham chiếu ngược. Một cái gì đó như sau,

\b(\w+)\b\W*=\W*\w*\W*\bas\b[\s\S]{1,150}(?!\b\1\b\W*==\W*\bnull\b) 
2

Câu hỏi không rõ ràng. Bạn muốn chính xác điều gì? Tôi rất tiếc, nhưng tôi vẫn không hiểu, sau khi đọc câu hỏi và bình luận nhiều lần.

.

Phải có mã trong C#? Trong Python? Khác?Không có dấu hiệu nào liên quan đến điểm này

.

Bạn có muốn đối sánh chỉ khi một dòng if(... == ...) theo sau một khối var ... = ... dòng?

Hoặc có thể một dòng không đồng nhất được GIỮA khối và đường dây if(... == ...) mà không dừng kết hợp?

Mã của tôi có tùy chọn thứ hai là đúng.

.

Đường dây if(... == null) SAU KHI một dòng if(... == ...) có dừng kết quả trùng khớp hay không?

Không thể hiểu nếu nó có hoặc không, tôi đã xác định hai regexes để nắm bắt hai tùy chọn này.

.

Tôi hy vọng mã của tôi sẽ đủ rõ ràng và trả lời cho mối bận tâm của bạn.

Nó là bằng Python

import re 

ch1 ='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 
1618987987849891 
''' 

ch2 ='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
uydtdrdutdutrr 
if(x1.a == y1.a) 
3213546878''' 

ch3='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1 == null) 
165478964654456454''' 

ch4='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
hgyrtdduihudgug 
if(x1 == null) 
165489746+54646544''' 

ch5='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(somethingunrelated == null) {...} 
if(x1.a == y1.a) 
1354687897''' 

ch6='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
ifughobviudyhogiuvyhoiuhoiv 
if(somethingunrelated == null) {...} 
if(x1.a == y1.a) 
2468748874897498749874897''' 

ch7 = '''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 
iufxresguygo 
liygcygfuihoiuguyg 
if(somethingunrelated == null) {...} 
oufxsyrtuy 
''' 

ch8 = '''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 
iufxresguygo 
liygcygfuihoiuguyg 
if(somethingunrelated == null) {...} 
oufxsyrtuy 
''' 

ch9 = '''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 
if(somethingunrelated == null) {...} 
oufxsyrtuy 
''' 

pat1 = re.compile(('(' 
        '(^var +\S+ *= *\S+ +as .+[\r\n]+)+?' 
        '([\s\S](?!==\s*null\\b))*?' 
        '^if *\(*[^\s=]+ *==(?!\s*null).+$' 
        ')' 
        ), 
        re.MULTILINE) 

pat2 = re.compile(('(' 
        '(^var +\S+ *= *\S+ +as .+[\r\n]+)+?' 
        '([\s\S](?!==\s*null\\b))*?' 
        '^if *\(*[^\s=]+ *==(?!\s*null).+$' 
        ')' 
        '(?![\s\S]{0,150}==)' 
        ), 
        re.MULTILINE) 


for ch in (ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8,ch9): 
    print pat1.search(ch).group() if pat1.search(ch) else pat1.search(ch) 
    print 
    print pat2.search(ch).group() if pat2.search(ch) else pat2.search(ch) 
    print '-----------------------------------------' 

quả

>>> 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 

var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
uydtdrdutdutrr 
if(x1.a == y1.a) 

var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
uydtdrdutdutrr 
if(x1.a == y1.a) 
----------------------------------------- 
None 

None 
----------------------------------------- 
None 

None 
----------------------------------------- 
None 

None 
----------------------------------------- 
None 

None 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 

None 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 

None 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 

None 
----------------------------------------- 
>>> 
+0

+1 Tôi đồng ý rằng câu hỏi này khá mơ hồ. Hầu hết mọi người không hiểu rằng một câu hỏi regex tốt phải được viết rất chính xác. – ridgerunner

2

Hãy để tôi cố gắng xác định lại vấn đề của bạn:

  1. Hãy tìm một "là" phân công - có thể bạn cần một regex tốt hơn để tìm các bài tập thực tế và có thể muốn lưu biểu thức được chỉ định, nhưng hãy sử dụng "\ bas \ b" bây giờ
  2. Nếu bạn thấy một if (... == null) trong vòng 150 ký tự, không phù hợp
  3. Nếu bạn không thấy một if (... == null) trong vòng 150 ký tự, trận đấu

biểu hiện của bạn \bas\b.{1,150}(?!\b==\s*null\b) sẽ không làm việc vì sự look- tiêu cực phía trước. Regex luôn có thể bỏ qua trước hoặc sau một chữ cái để tránh cái nhìn tiêu cực này và bạn sẽ kết hợp ngay cả khi có một số if (... == null) ở đó.

Regex thực sự không tốt ở số không phải khớp với nội dung nào đó. Trong trường hợp này, bạn nên cố gắng để phù hợp với một "là" chuyển nhượng với một "nếu == null" kiểm tra trong vòng 150 ký tự:

\bas\b.{1,150}\b==\s*null\b 

và sau đó phủ nhận việc kiểm tra: if (!regex.match(text)) ...

1
(?s:\s+as\s+(?!.{0,150}==\s*null\b)) 

Tôi đang kích hoạt tùy chọn SingleLine với ?s:. Bạn có thể đặt nó trong các tùy chọn của Regex của bạn nếu bạn muốn. Tôi sẽ thêm rằng tôi đang đặt \s xung quanh as vì tôi cho rằng chỉ các khoảng trống "hợp pháp" xung quanh as. Bạn có lẽ có thể đưa \b như

(?s:\b+as\b(?!.{0,150}==\s*null\b)) 

Hãy nhận biết rằng \s lẽ sẽ bắt không gian mà không phải là "không gian hợp lệ".Nó được định nghĩa là [\f\n\r\t\v\x85\p{Z}] trong đó \p{Z}Unicode Characters in the 'Separator, Space' Category cộng Unicode Characters in the 'Separator, Line' Category cộng với Unicode Characters in the 'Separator, Paragraph' Category.

Các vấn đề liên quan