2013-06-27 35 views
17

Tôi đang làm việc trên thư viện JavaScript của riêng mình để hỗ trợ các siêu ký tự và tính năng mới cho cụm từ thông dụng và tôi muốn tìm trường hợp [^xy] không tương đương với (?!x). (hoặc cụ thể hơn (?:(?!x|y).)).Có trường hợp "[^ xy]" không bằng "(?! X | y)."?

Lấy văn bản Ví dụ: "abc\n"

Nói rằng tôi muốn mô phỏng một regex Perl: /\A.{3}\Z/s

Với cờ singleline, regex JavaScript nên tương đương với: /^[\s\S]{3}\n*$(?!\s)/ (\A trở thành ^, . trở thành [\s\S] , \Z trở thành \n*$(?!\s))

Bây giờ, /^.{3}$/ sẽ không thành công, nhưng /^[\s\S]{3}\n*$(?!\s)/ sẽ c apture "abcabc" (giống như regex Perl)

Vì số \Z có chứa nhiều hơn một metacharacter, mô phỏng [^\Z] có vẻ khó khăn hơn.

Lấy văn bản Ví dụ: "abcabc\n"

đề xuất regex JavaScript cho regex Perl /.{3}[^\Za]/g sẽ .{3}(?:(?!\n*$(?!\s)|a).)/g

Cả hai sẽ phù hợp "bcab"

Vì vậy, cuối cùng, tôi đưa ra câu hỏi một lần nữa. Có một trường hợp mà [^xy] không tương đương với (?:(?!x|y).) với một kịch bản như vậy, có lẽ trong một biểu thức chính quy phức tạp hơn, nơi một lookahead sẽ thay đổi kịch bản?

+0

'/^[\ s \ S] {3} \ n * $ (?! \ S) /. Exec (" abcabc \ n ")' không khớp với tôi và không cung cấp 'abcabc' như bạn đề xuất – Eric

+0

Cũng không phải regex perl '/ \ A. {3} \ Z/s' khớp '' abcabc \ n "', như bạn đã xác nhận ... – Eric

+0

Đúng. Tôi đã thay đổi một số thứ xung quanh và quên chỉnh sửa chúng. Kịch bản đầu tiên sử dụng văn bản "abc \ n" và kịch bản thứ hai sử dụng văn bản "abcabc \ n". Tôi đã chỉnh sửa bài đăng chính. –

Trả lời

5

Có trường hợp nào [^xy] không bằng (?!x|y).?

Chỉ một tài khoản bạn đã mô tả: Dấu chấm JS không khớp với dòng mới và cần được thay thế bằng [\s\S].

\Z trở thành \n$(?!\s)

Điều đó có vẻ sai. Sau khi kết thúc chuỗi (\z/$) sẽ không bao giờ có bất cứ điều gì, bất kể khoảng trắng hay không. Afaik, \Z là một zero-width-khẳng định (nó không tiêu thụ xuống dòng (s)) và nên được tương đương với

(?=\n*$) 
// ^not sure whether ? or * 

Kể từ \Z chứa nhiều hơn chỉ là một metacharater, bắt chước [^\Z] sẽ dường như khó khăn hơn.

Ý bạn là gì bởi "metacharacter"? Đó là xác nhận chiều rộng bằng 0 và không có ý nghĩa nhiều trong lớp nhân vật. Tôi đoán đó là lỗi cú pháp hoặc sẽ được diễn giải theo nghĩa đen (không thoát) như [^Z].

+0

Lỗi: \ Z trở thành \ n * $ (?! \ S). Trong Perl, \ Z tương đương với \ n * \ z. \ z chỉ đúng ở cuối chuỗi. Do đó, nếu \ z là $ (?! \ S), thì \ Z là \ n * $ (?! \ S). Có vẻ như tôi đã bắt đầu suy nghĩ quá nhiều thứ với toàn bộ ý tưởng "chuyển đổi" này. Bạn hoàn toàn đúng về [^ \ Z] trở thành [^ Z]. Tôi nghĩ rằng tôi cần một break từ lập trình, cảm ơn cho cái nhìn sâu sắc. :) –

+1

@JoeySchooley điểm là rằng '\ n' không được bao gồm trong trận đấu. Vì vậy, '\ n' thuộc về một lookahead (và tôi không chắc chắn về các ngôi sao sau khi' \ n') –

+0

Tôi đã thực hiện một chỉnh sửa trong bình luận ở trên nhưng có vẻ như bạn đánh tôi. Cảm ơn bạn đã xem xét vấn đề thực tế của lý luận của tôi. –

4

[^xy] sẽ khớp với \n. (?!x|y). sẽ không phù hợp \n theo mặc định (vì . không phù hợp \n)

Tôi không tin javascript có một "dotall" hoặc "single-line" modifier, nhưng với phiên bản mới của mỗi trình duyệt đánh mỗi vài tháng, tôi đã mất dấu vết.

9

Đối với chuỗi đầu vào "x\na", 2 regexps cung cấp các đầu ra khác nhau, vì . không khớp với dòng mới.

console.log("x\na".match(/(?:(?!x|y).)/)) 
["a", index: 2, input: "x↵a"] 
console.log("x\na".match(/[^xy]/)) 
["↵", index: 1, input: "x↵a"] 

Nếu bạn thay đổi .-[\s\S], đầu ra là giống hệt nhau trong trường hợp này:

console.log("x\na".match(/(?:(?!x|y)[\s\S])/)) 
["↵", index: 1, input: "x↵a"] 

Tôi không thể nghĩ ra bất kỳ trường hợp khác ngay bây giờ.

0

Như những người khác đã nói, bạn nên sử dụng [\s\S] thay vì . để thay thế. Nếu không, nếu bạn đang thực hiện phép chuyển đổi đó chỉ qua các chuỗi ký tự, có một vài điều cần phải quan tâm. Đặc biệt, các ký tự meta và chuỗi thoát:

[^*)] => (?!\*|\))[\s\S] 

Nhưng tôi đoán bạn sẽ cần phải cẩn thận phân tích cú pháp và viết ký tự đặc biệt.

Điều khó nhất có lẽ là \b mặc dù, vì đó là một ký tự (backspace) trong các lớp ký tự và một ranh giới từ bên ngoài. Vì vậy, trong thay thế, bạn phải đi với một bát phân hoặc hệ thập lục phân thoát:

[^a\b] => (?!a|\10)[\s\S] 
    or => (?!a|\x08)[\s\S] 

Khác hơn, hai nên luôn luôn là tương đương.

0

Một trường hợp định dạng [^xy] là không giống như (?:(?!x|y).) sẽ là trong đó x là một sự khẳng định chiều rộng không thay sau đó một nhân vật thực tế như:

Với văn bản mẫu này: ab-yz

Regex: [^\by] Ví dụ : http://www.rubular.com/r/ERKrqyeAs9

Returns:

[0] => a 
[1] => b 
[2] => - 
[3] => z 

Trong khi

Regex: (?:(?!\b|y).) dụ: http://www.rubular.com/r/V5RdyQEQo5

Returns:

[0] => b 
[1] => z 

biểu khác không tương đương, những phần lớn tập trung vào thực tế là cùng một cú pháp có meenings khác nhau bên trong hoặc bên ngoài lớp nhân vật:

  • [^^y] sản lượng a, b, -, z không bằng (?:(?!^|y).) sản lượng b, -, z
  • [^.y] mang a, b, -, z không bằng (?:(?!.|y).) mang lại gì

Hoặc bạn có thể thử điều này trong unicode nugget trong Perl: http://ideone.com/2xMfkQ

print "\ncapture\n"; 
@m = ("ss" =~ m/^(?:(?!\xDF|y).)+$/ui); 
print for @m; 

print "\nclass\n"; 
@m = ("ss" =~ m/^[^\xDFy]+$/ui) ; 
print for @m; 

Sản lượng:

capture 

class 
1 
+0

Ranh giới từ trong một lớp nhân vật có ý nghĩa gì đối với bạn? – Bergi

+0

Nó không có ý nghĩa gì với tôi, tuy nhiên câu hỏi của Joey là 'Tôi muốn tìm một trường hợp mà [^ xy] không tương đương (? :(?! x | y).)).' Và đây là một biểu thức đúng ngữ pháp mang lại kết quả khác biệt rõ rệt. –

+0

Vâng '[^ \ by]' không đúng về mặt ngữ pháp đối với tôi. Trong kết quả bạn nhận được nó được hiểu là '[^ by]', mà * là * tương đương với '(?! B | y) .' – Bergi

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