Biểu thức chính quy có thể đọc được mà không mất sức?


77

Nhiều lập trình viên biết niềm vui của việc đưa ra một biểu thức chính quy nhanh chóng, những ngày này thường với sự trợ giúp của một số dịch vụ web, hoặc theo truyền thống hơn tại dấu nhắc tương tác, hoặc có thể viết một tập lệnh nhỏ có biểu thức chính quy đang được phát triển và một tập hợp các trường hợp thử nghiệm . Trong cả hai trường hợp, quá trình này lặp đi lặp lại và khá nhanh chóng: tiếp tục hack tại chuỗi tìm kiếm khó hiểu cho đến khi nó khớp và nắm bắt những gì bạn muốn và sẽ từ chối những gì bạn không muốn.

Đối với một kết quả trường hợp đơn giản có thể là một cái gì đó như thế này, như là một biểu thức chính quy của Java:

Pattern re = Pattern.compile(
  "^\\s*(?:(?:([\\d]+)\\s*:\\s*)?(?:([\\d]+)\\s*:\\s*))?([\\d]+)(?:\\s*[.,]\\s*([0-9]+))?\\s*$"
);

Nhiều lập trình viên cũng biết nỗi đau của việc cần phải chỉnh sửa một biểu thức chính quy, hoặc chỉ viết mã xung quanh một biểu thức chính quy trong một cơ sở mã kế thừa. Với một chút chỉnh sửa để phân tách nó, regrec ở trên vẫn rất dễ hiểu đối với bất kỳ ai quen thuộc với regexps, và một cựu chiến binh regrec nên xem ngay những gì nó làm (trả lời ở cuối bài, trong trường hợp ai đó muốn tập thể dục tự tìm ra nó).

Tuy nhiên, mọi thứ không cần phải trở nên phức tạp hơn nhiều cho một regexp để trở nên thực sự viết chỉ điều, và ngay cả với tài liệu hướng dẫn siêng năng (mà tất cả mọi người tất nhiên không cho tất cả regexps phức tạp họ viết ...), sửa đổi regexps trở thành một nhiệm vụ khó khăn. Nó có thể là một nhiệm vụ rất nguy hiểm quá, nếu regexp không phải là cẩn thận đơn vị thử nghiệm (nhưng tất cả mọi người tất nhiên có kiểm tra đơn vị toàn diện cho tất cả regexps phức tạp của họ, cả tích cực lẫn tiêu cực ...).

Vì vậy, câu chuyện dài ngắn, có một giải pháp đọc / thay thế cho các biểu thức thông thường mà không mất sức? Làm thế nào các regrec ở trên trông như thế nào với một phương pháp thay thế? Bất kỳ ngôn ngữ nào cũng tốt, mặc dù một giải pháp đa ngôn ngữ sẽ là tốt nhất, với các biểu thức chính quy là đa ngôn ngữ.


Và sau đó, những gì regrec trước đó làm là: phân tích một chuỗi số theo định dạng 1:2:3.4, bắt từng số, trong đó khoảng trắng được cho phép và chỉ 3được yêu cầu.


2
điều liên quan trên SO: stackoverflow.com/a/143636/674039
wim

24
Đọc / chỉnh sửa regexes thực sự không quan trọng nếu bạn biết những gì họ cần phải nắm bắt. Bạn có thể đã nghe nói về tính năng hiếm khi được sử dụng này của hầu hết các ngôn ngữ được gọi là "bình luận". Nếu bạn không đặt một mức trên một biểu thức phức tạp giải thích những gì nó sẽ trả giá sau này. Ngoài ra, xem xét mã.
TC1

2
Hai tùy chọn để làm sạch cái này mà không thực sự phá vỡ nó thành những mảnh nhỏ hơn. Sự hiện diện hay vắng mặt của họ thay đổi từ ngôn ngữ này sang ngôn ngữ khác. (1) regex dòng mở rộng, trong đó khoảng trắng trong regex bị bỏ qua (trừ khi thoát) và một hình thức nhận xét một dòng được thêm vào, do đó bạn có thể chia nó thành các đoạn logic với thụt lề, giãn dòng và nhận xét. (2) các nhóm chụp được đặt tên, trong đó bạn có thể đặt tên cho từng ngoặc đơn, cả hai đều thêm một số tài liệu tự động và tự động điền một hàm băm khớp - tốt hơn cả một mảng khớp được lập chỉ mục bằng số hoặc biến $ N.
Ben Lee

3
Một phần của vấn đề là chính ngôn ngữ regex và các lựa chọn lịch sử tồi tệ trong thiết kế của nó bị kéo theo như hành lý. Trong một ngôn ngữ lành mạnh, nhóm dấu ngoặc đơn thuần là một thiết bị cú pháp để định hình cây phân tích cú pháp. Nhưng trong các triển khai regex quay trở lại Unix họ có ngữ nghĩa: các thanh ghi ràng buộc cho các kết quả phụ. Vì vậy, sau đó bạn cần một số dấu ngoặc phức tạp, xấu xí hơn chỉ để đạt được nhóm thuần túy!
Kaz

2
Không thực sự là một câu trả lời thực tế, nhưng có thể hữu ích khi đề cập rằng sức mạnh của biểu thức chính quy là chính xác như của một máy tự động hữu hạn. Đó là, regexes có thể xác nhận / phân tích cùng một loại chuỗi được xác thực và phân tích cú pháp bởi các máy tự động hữu hạn. Do đó, một đại diện có thể đọc được của con người về một biểu thức chính quy có thể có thể nhanh chóng xây dựng một biểu đồ và tôi tin rằng hầu hết các ngôn ngữ dựa trên văn bản đều thực sự xấu về nó; đó là lý do tại sao chúng tôi sử dụng các công cụ trực quan cho những thứ như vậy. Hãy xem hackingoff.com/compilers/THER-expression-to-nfa-dfa để lấy cảm hứng.
damix911

Câu trả lời:


80

Một số người đã đề cập đến việc sáng tác từ các phần nhỏ hơn, nhưng chưa có ai cung cấp một ví dụ nào, vì vậy đây là của tôi:

string number = "(\\d+)";
string unit = "(?:" + number + "\\s*:\\s*)";
string optionalDecimal = "(?:\\s*[.,]\\s*" + number + ")?";

Pattern re = Pattern.compile(
  "^\\s*(?:" + unit + "?" + unit + ")?" + number + optionalDecimal + "\\s*$"
);

Không phải là dễ đọc nhất, nhưng tôi cảm thấy như nó rõ ràng hơn bản gốc.

Ngoài ra, C # có @toán tử có thể được thêm vào một chuỗi để chỉ ra rằng nó sẽ được lấy theo nghĩa đen (không có ký tự thoát), vì vậy numbersẽ là@"([\d]+)";


Bây giờ mới nhận thấy cả hai [\\d]+[0-9]+nên như thế nào \\d+(tốt, một số có thể tìm thấy [0-9]+dễ đọc hơn). Tôi sẽ không chỉnh sửa câu hỏi, nhưng bạn có thể muốn sửa câu trả lời này.
hyde

@hyde - Bắt tốt. Về mặt kỹ thuật, chúng không hoàn toàn giống nhau - \dsẽ khớp với bất kỳ thứ gì được coi là số, ngay cả trong các hệ thống đánh số khác (tiếng Trung, tiếng Ả Rập, v.v.), trong khi [0-9]sẽ chỉ khớp với các chữ số tiêu chuẩn. \\dMặc dù vậy, tôi đã chuẩn hóa và đưa nó vào optionalDecimalmẫu.
Bobson

42

Chìa khóa để ghi lại biểu thức chính quy là ghi lại nó. Quá thường xuyên mọi người ném vào những gì dường như là tiếng ồn đường và để nó ở đó.

Trong perl các /xnhà điều hành ở phần cuối của biểu thức chính quy ngăn chặn khoảng trắng cho phép một để ghi lại biểu thức chính quy.

Biểu thức chính quy ở trên sẽ trở thành:

$re = qr/
  ^\s*
  (?:
    (?:       
      ([\d]+)\s*:\s*
    )?
    (?:
      ([\d]+)\s*:\s*
    )
  )?
  ([\d]+)
  (?:
    \s*[.,]\s*([\d]+)
  )?
  \s*$
/x;

Vâng, nó hơi tiêu tốn khoảng trắng dọc, mặc dù người ta có thể rút ngắn nó mà không mất quá nhiều khả năng đọc.

Và sau đó, những gì regrec trước đó làm là: phân tích một chuỗi số ở định dạng 1: 2: 3.4, chụp từng số, trong đó khoảng trắng được cho phép và chỉ cần 3 số.

Nhìn vào biểu thức chính quy này, người ta có thể thấy nó hoạt động như thế nào (và không hoạt động). Trong trường hợp này, regex này sẽ khớp với chuỗi 1.

Cách tiếp cận tương tự có thể được thực hiện trong ngôn ngữ khác. Tùy chọn re.VERBOSE python hoạt động ở đó.

Perl6 (ví dụ trên là cho perl5) đưa vấn đề này đi xa hơn với khái niệm quy tắc dẫn đến các cấu trúc thậm chí còn mạnh hơn PCRE (nó cung cấp quyền truy cập vào các ngữ pháp khác (không có ngữ cảnh và ngữ cảnh) so với chỉ các quy tắc thông thường và mở rộng).

Trong Java (nơi ví dụ này lấy từ), người ta có thể sử dụng nối chuỗi để tạo biểu thức chính quy.

Pattern re = Pattern.compile(
  "^\\s*"+
  "(?:"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #1
    ")?"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #2
    ")"+
  ")?"+ // First groups match 0 or 1 times
  "([\\d]+)"+ // Capture group #3
  "(?:\\s*[.,]\\s*([0-9]+))?"+ // Capture group #4 (0 or 1 times)
  "\\s*$"
);

Phải thừa nhận rằng, điều này tạo ra nhiều hơn "trong chuỗi có thể dẫn đến một số nhầm lẫn ở đó, có thể dễ đọc hơn (đặc biệt là với cú pháp tô sáng trên hầu hết các IDE) và được ghi lại.

Điều quan trọng là nhận ra sức mạnh và bản chất "viết một lần" mà các biểu thức thông thường thường rơi vào. Viết mã để phòng thủ tránh điều này để biểu thức chính quy vẫn rõ ràng và dễ hiểu là chìa khóa. Chúng tôi định dạng mã Java cho rõ ràng - các biểu thức thông thường không khác nhau khi ngôn ngữ cung cấp cho bạn tùy chọn để làm như vậy.


13
Có một sự khác biệt lớn giữa "tài liệu" và "thêm ngắt dòng".

4
@Jonof ALLTrades Làm cho mã có thể được đọc là bước đầu tiên cho bất cứ điều gì. Việc thêm ngắt dòng cũng cho phép một người thêm nhận xét cho tập hợp con RE đó trên cùng một dòng (điều khó thực hiện hơn trên một dòng dài của văn bản biểu thức chính quy).

2
@Jonof ALLTrades, tôi không đồng ý khá mạnh mẽ. "Tài liệu" và "thêm ngắt dòng" không khác nhau ở chỗ cả hai đều phục vụ cùng một mục đích - làm cho mã dễ hiểu hơn. Và đối với mã được định dạng kém, "thêm ngắt dòng" phục vụ mục đích đó tốt hơn nhiều so với việc thêm tài liệu.
Ben Lee

2
Thêm ngắt dòng là một sự khởi đầu, nhưng đó là khoảng 10% công việc. Các câu trả lời khác cung cấp chi tiết cụ thể hơn, rất hữu ích.

26

Chế độ "dài dòng" được cung cấp bởi một số ngôn ngữ và thư viện là một trong những câu trả lời cho những mối quan tâm này. Trong chế độ này, khoảng trắng trong chuỗi regrec bị loại bỏ (vì vậy bạn cần sử dụng \s) và có thể nhận xét. Đây là một ví dụ ngắn trong Python hỗ trợ điều này theo mặc định:

email_regex = re.compile(r"""
    ([\w\.\+]+) # username (captured)
    @
    \w+         # minimal viable domain part
    (?:\.w+)    # rest of the domain, after first dot
""", re.VERBOSE)

Trong bất kỳ ngôn ngữ nào không có, thực hiện một trình dịch từ chế độ dài sang chế độ "bình thường" sẽ là một nhiệm vụ đơn giản. Nếu bạn lo lắng về khả năng đọc của regexps của mình, có lẽ bạn sẽ biện minh cho việc đầu tư lần này khá dễ dàng.


15

Mỗi ngôn ngữ sử dụng biểu thức chính quy cho phép bạn soạn chúng từ các khối đơn giản hơn để đọc dễ dàng hơn và với bất kỳ điều gì phức tạp hơn (hoặc phức tạp như) ví dụ của bạn, bạn chắc chắn nên tận dụng tùy chọn đó. Vấn đề đặc biệt với Java và nhiều ngôn ngữ khác là họ không coi các biểu thức chính quy là công dân "hạng nhất", thay vào đó yêu cầu họ phải lén lút sử dụng ngôn ngữ thông qua các chuỗi ký tự. Điều này có nghĩa là nhiều dấu ngoặc kép và dấu gạch chéo ngược không thực sự là một phần của cú pháp regex và khiến mọi thứ khó đọc, và điều đó cũng có nghĩa là bạn không thể đọc được nhiều hơn thế mà không cần xác định một cách hiệu quả ngôn ngữ và trình thông dịch mini của riêng bạn.

Tất nhiên, cách tốt nhất để tích hợp các biểu thức chính quy là Perl, với tùy chọn khoảng trắng và toán tử trích dẫn biểu thức chính quy. Perl 6 mở rộng khái niệm xây dựng các biểu thức chính tả từ các bộ phận đến các ngữ pháp đệ quy thực tế, điều này tốt hơn rất nhiều để sử dụng nó thực sự không có so sánh nào cả. Ngôn ngữ có thể đã bỏ lỡ con thuyền của sự kịp thời, nhưng hỗ trợ regex của nó là The Good Stuff (tm).


1
Bằng "các khối đơn giản hơn" được đề cập ở đầu câu trả lời, bạn có nghĩa chỉ là nối chuỗi, hoặc một cái gì đó cao cấp hơn?
hyde

7
Tôi có nghĩa là xác định các biểu thức phụ là các chuỗi ký tự ngắn hơn, gán chúng cho các biến cục bộ với các tên có ý nghĩa và sau đó ghép nối. Tôi thấy các tên quan trọng đối với khả năng đọc hơn là chỉ cải thiện bố cục.
Kilian Foth

11

Tôi thích sử dụng Expresso: http://www.ultrapico.com/Expresso.htm

Ứng dụng miễn phí này có các tính năng sau mà tôi thấy hữu ích theo thời gian:

  • Bạn có thể chỉ cần sao chép và dán regex của mình và ứng dụng sẽ phân tích cú pháp cho bạn
  • Khi regex của bạn được viết, bạn có thể kiểm tra nó trực tiếp từ ứng dụng (ứng dụng sẽ cung cấp cho bạn danh sách các ảnh chụp, thay thế ...)
  • Khi bạn đã kiểm tra nó, nó sẽ tạo mã C # để triển khai nó (lưu ý rằng mã sẽ chứa các giải thích về regex của bạn).

Ví dụ: với regex bạn vừa gửi, nó sẽ trông như sau: Màn hình mẫu với regex ban đầu

Tất nhiên, cho nó một thử là đáng giá một ngàn từ mô tả nó. Cũng xin lưu ý rằng tôi lưu ý liên quan theo bất kỳ cách nào với trình chỉnh sửa của ứng dụng này.


4
bạn có thể giải thích về điều này chi tiết hơn - làm thế nào và tại sao nó trả lời câu hỏi được hỏi? "Câu trả lời chỉ liên kết" không được chào đón tại Stack Exchange
gnat

5
@gnat Xin lỗi về điều đó. Bạn hoàn toàn đúng. Tôi hy vọng rằng câu trả lời được chỉnh sửa của tôi sẽ cung cấp nhiều thông tin chi tiết hơn.
E. Jaep

9

Đối với một số điều, có thể chỉ cần sử dụng một ngữ pháp như BNF. Đây có thể là dễ đọc hơn nhiều so với biểu thức thông thường. Sau đó, một công cụ như GoldParser Builder có thể chuyển đổi ngữ pháp thành trình phân tích cú pháp giúp nâng đỡ bạn rất nhiều.

Các ngữ pháp BNF, EBNF, v.v. có thể dễ đọc và dễ đọc hơn nhiều so với một biểu thức thông thường phức tạp. VÀNG là một công cụ cho những thứ đó.

Liên kết wiki c2 dưới đây có một danh sách các lựa chọn thay thế có thể được tách ra, với một số thảo luận về chúng. Về cơ bản, đây là một liên kết "xem thêm" để đề xuất công cụ ngữ pháp của tôi:

Các lựa chọn thay thế cho các biểu thức thông thường

Lấy "thay thế" để có nghĩa là "cơ sở tương đương về mặt ngữ nghĩa với các cú pháp khác nhau", có ít nhất những lựa chọn thay thế này cho / với RoutExpressions:

  • Biểu thức chính quy cơ bản
  • Biểu thức chính quy "mở rộng"
  • Biểu thức chính quy tương thích Perl
  • ... và nhiều biến thể khác ...
  • Cú pháp RE kiểu SNOBOL (SnobolL Language, IconL Language)
  • Cú pháp SRE (RE's as EssExpressions)
  • các tổng hợp FSM khác nhau
  • Ngữ pháp giao điểm trạng thái hữu hạn (khá biểu cảm)
  • ParsingExpressionGrammars, như trong OMetaL Language và LuaL Language ( http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html )
  • Chế độ phân tích cú pháp của RebolL Language
  • Xác suấtBaseParsing ...

bạn có phiền giải thích thêm về những gì liên kết này làm và những gì nó tốt cho? "Câu trả lời chỉ liên kết" không được chào đón tại Stack Exchange
gnat

1
Chào mừng bạn đến với Lập trình viên, Nick P. Vui lòng bỏ qua downvote / r, nhưng hãy đọc trang trên meta mà @gnat liên kết đến.
Christoffer Lette

@ Christoffer Lette Đánh giá cao câu trả lời của bạn. Sẽ cố gắng ghi nhớ điều này trong các bài viết trong tương lai. @ gnat Nhận xét của Paulo Scardine phản ánh ý định của bài viết của tôi. Các ngữ pháp BNF, EBNF, v.v. có thể dễ đọc và dễ đọc hơn nhiều so với một biểu thức thông thường phức tạp. VÀNG là một công cụ cho những thứ đó. Liên kết c2 có một danh sách các lựa chọn thay thế có thể được tách ra, với một số thảo luận về chúng. Về cơ bản, nó là một liên kết "xem thêm" để đưa ra khuyến nghị về ngữ pháp của tôi.
Nick P

6

Đây là một câu hỏi cũ và tôi không thấy bất kỳ đề cập nào về Biểu thức bằng lời nói vì vậy tôi nghĩ rằng tôi sẽ thêm thông tin đó vào đây cho những người tìm kiếm trong tương lai. Biểu thức bằng lời nói được thiết kế đặc biệt để làm cho regex trở nên dễ hiểu với con người, mà không cần phải tìm hiểu ý nghĩa biểu tượng của regex. Xem ví dụ sau. Tôi nghĩ rằng điều này làm tốt nhất những gì bạn đang yêu cầu.

// Create an example of how to test for correctly formed URLs
var tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

// Create an example URL
var testMe = 'https://www.google.com';

// Use RegExp object's native test() function
if (tester.test(testMe)) {
    alert('We have a correct URL '); // This output will fire}
} else {
    alert('The URL is incorrect');
}

console.log(tester); // Outputs the actual expression used: /^(http)(s)?(\:\/\/)(www\.)?([^\ ]*)$/

Ví dụ này dành cho javascript, bạn có thể tìm thấy thư viện này ngay bây giờ cho nhiều ngôn ngữ lập trình.


2
Điều này thật tuyệt!
Jeremy Thompson

3

Cách đơn giản nhất là vẫn sử dụng regex nhưng xây dựng biểu thức của bạn từ việc soạn các biểu thức đơn giản hơn với các tên mô tả, ví dụ: http://www.martinfowler.com/bliki/ComposesRegex.html (và vâng, đây là từ concat chuỗi)

tuy nhiên, để thay thế, bạn cũng có thể sử dụng thư viện trình kết hợp trình phân tích cú pháp, ví dụ: http://jparsec.codehaus.org/ sẽ cung cấp cho bạn trình phân tích cú pháp đệ quy đầy đủ. một lần nữa sức mạnh thực sự ở đây đến từ thành phần (lần này là thành phần chức năng).


3

Tôi nghĩ rằng nó muốn được đáng nói logstash của grok biểu thức. Grok xây dựng dựa trên ý tưởng soạn các biểu thức phân tích cú pháp dài từ các biểu thức ngắn hơn. Nó cho phép thử nghiệm thuận tiện các khối xây dựng này và được đóng gói sẵn với hơn 100 mẫu thường được sử dụng . Khác với các mẫu này, nó cho phép sử dụng tất cả các cú pháp biểu thức thông thường.

Mẫu trên được thể hiện trong Grok là (Tôi đã thử nghiệm trong ứng dụng trình gỡ lỗi nhưng có thể đã bị lỗi):

"(( *%{NUMBER:a} *:)? *%{NUMBER:b} *:)? *%{NUMBER:c} *(. *%{NUMBER:d} *)?"

Các bộ phận và không gian tùy chọn làm cho nó trông hơi xấu hơn bình thường, nhưng cả ở đây và trong các trường hợp khác, sử dụng Grok có thể làm cho cuộc sống của một người đẹp hơn nhiều.


2

Trong F #, bạn có mô-đun FsVerbalExpressions . Nó cho phép bạn soạn Regexes từ các biểu thức bằng lời nói, nó cũng có một số regexes dựng sẵn (như URL).

Một trong những ví dụ cho cú pháp này là như sau:

let groupName =  "GroupNumber"

VerbEx()
|> add "COD"
|> beginCaptureNamed groupName
|> any "0-9"
|> repeatPrevious 3
|> endCapture
|> then' "END"
|> capture "COD123END" groupName
|> printfn "%s"

// 123

Nếu bạn không quen với cú pháp F #, groupName là chuỗi "GroupNumber".

Sau đó, họ tạo Biểu thức bằng lời nói (VerbEx) mà họ xây dựng là "COD (? <GroupNumber> [0-9] {3}) END". Sau đó, họ kiểm tra chuỗi "COD123END", tại đó họ nhận được nhóm bắt giữ có tên "GroupNumber". Kết quả này trong 123.

Tôi thành thật tìm thấy regex bình thường dễ hiểu hơn nhiều.


-2

Đầu tiên, hiểu rằng mã mà chỉ hoạt động là mã xấu. Mã tốt cũng cần báo cáo chính xác bất kỳ lỗi nào gặp phải.

Ví dụ: nếu bạn đang viết một chức năng để chuyển tiền từ tài khoản của người dùng này sang tài khoản của người dùng khác; bạn sẽ không trả lại một boolean "đã làm việc hoặc thất bại" bởi vì điều đó không cung cấp cho người gọi bất kỳ ý tưởng nào về sự cố và không cho phép người gọi thông báo chính xác cho người dùng. Thay vào đó, bạn có thể có một bộ mã lỗi (hoặc một bộ ngoại lệ): không thể tìm thấy tài khoản đích, không đủ tiền trong tài khoản nguồn, quyền bị từ chối, không thể kết nối với cơ sở dữ liệu, tải quá nhiều (thử lại sau), v.v. .

Bây giờ hãy nghĩ về ví dụ "phân tích một chuỗi số theo định dạng 1: 2: 3,4" của bạn. Tất cả các biểu thức chính là báo cáo "vượt qua / thất bại" không cho phép phản hồi đầy đủ được trình bày cho người dùng (cho dù phản hồi này là thông báo lỗi trong nhật ký hay GUI tương tác trong đó các lỗi được hiển thị màu đỏ như loại người dùng, hoặc bất cứ điều gì khác). Những loại lỗi nào mà nó không mô tả đúng? Ký tự xấu trong số đầu tiên, số đầu tiên quá lớn, thiếu dấu hai chấm sau số đầu tiên, v.v.

Để chuyển đổi "mã xấu chỉ đơn thuần hoạt động" thành "mã tốt cung cấp các lỗi mô tả đầy đủ", bạn phải chia regex thành nhiều biểu thức nhỏ hơn (thông thường, các biểu thức nhỏ đến mức dễ dàng thực hiện mà không cần regex ngay từ đầu ).

Làm cho mã có thể đọc / duy trì được chỉ là một hệ quả ngẫu nhiên của việc làm cho mã tốt.


6
Có lẽ không phải là một giả định tốt. Của tôi là vì A) Điều này không giải quyết được câu hỏi ( Làm thế nào để làm cho nó dễ đọc?), B) Kết hợp biểu thức chính quy vượt qua / thất bại và nếu bạn chia nhỏ nó đến điểm mà bạn có thể nói chính xác tại sao nó thất bại, bạn mất rất nhiều sức mạnh và tốc độ, và làm tăng sự phức tạp, C) Không có dấu hiệu nào cho thấy câu hỏi thậm chí có khả năng trận đấu thất bại - đó đơn giản chỉ là câu hỏi về việc làm cho Regex có thể đọc được. Khi bạn có quyền kiểm soát dữ liệu đi vào và / hoặc xác thực dữ liệu trước khi xử lý, bạn có thể cho rằng nó hợp lệ.
Bobson

A) Chia nó thành các phần nhỏ hơn làm cho nó dễ đọc hơn (như là kết quả của việc làm cho nó tốt). C) Khi các chuỗi không xác định / không được xác thực nhập vào một phần mềm, nhà phát triển lành mạnh sẽ phân tích cú pháp (có báo cáo lỗi) tại thời điểm đó và chuyển đổi dữ liệu thành một hình thức không cần phải sửa lại - sau đó không cần regex. B) là vô nghĩa chỉ áp dụng cho mã xấu (tham khảo điểm A và C).
Brendan

Đi từ C của bạn: Nếu đây logic xác thực của anh ấy thì sao? Mã của OP có thể chính xác là những gì bạn đề xuất - xác thực đầu vào, báo cáo nếu nó không hợp lệ và chuyển đổi nó thành một hình thức có thể sử dụng (thông qua các ảnh chụp). Tất cả chúng ta có là biểu hiện chính nó. Làm thế nào bạn có thể đề nghị phân tích cú pháp khác với regex? Nếu bạn thêm một số mã mẫu sẽ đạt được kết quả tương tự, tôi sẽ xóa downvote của tôi.
Bobson

Nếu đây là "C: Xác thực (có báo cáo lỗi)" thì đó là mã xấu vì báo cáo lỗi là xấu. Nếu thất bại; Có phải vì chuỗi là NULL hay vì số đầu tiên có quá nhiều chữ số hoặc bởi vì dấu phân cách đầu tiên không phải là :? Hãy tưởng tượng một trình biên dịch chỉ có một thông báo lỗi ("LRI") quá ngu ngốc để nói cho người dùng biết vấn đề là gì. Bây giờ hãy tưởng tượng hàng ngàn trang web thật ngu ngốc và hiển thị (ví dụ) "Địa chỉ email xấu" và không có gì nữa.
Brendan

Ngoài ra, hãy tưởng tượng một người vận hành bàn trợ giúp được đào tạo một nửa nhận được báo cáo lỗi từ một người dùng hoàn toàn không được huấn luyện nói rằng: Phần mềm đã ngừng hoạt động - dòng cuối cùng trong nhật ký của phần mềm là "LRI: Không thể trích xuất số phiên bản nhỏ từ chuỗi phiên bản '1: 2-3.4 '(Đại tràng dự kiến ​​sau số thứ hai) "
Brendan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.