2015-10-11 16 views
5

Không có câu hỏi nào về SO giải quyết vấn đề cụ thể của tôi. Tôi biết rất ít về biểu hiện chính quy. Tôi đang xây dựng một trình phân tích biểu thức trong Java bằng cách sử dụng Regex Class cho mục đích đó. Tôi muốn trích xuất Operands, Arguments, Operators, Symbols và Function Names từ biểu thức và sau đó lưu vào ArrayList. Hiện nay tôi đang sử dụng logic nàyCụm từ thông dụng để trích xuất toán tử từ biểu thức toán học

String string = "2!+atan2(3+9,2+3)-2*PI+3/3-9-12%3*sin(9-9)+(2+6/2)" //This is just for testing purpose later on it will be provided by user 
List<String> res = new ArrayList<>(); 
Pattern pattern = Pattern.compile((\\Q^\\E|\\Q/\\E|\\Q-\\E|\\Q-\\E|\\Q+\\E|\\Q*\\E|\\Q)\\E|\\Q)\\E|\\Q(\\E|\\Q(\\E|\\Q%\\E|\\Q!\\E)) //This string was build in a function where operator names were provided. Its mean that user can add custom operators and custom functions 
Matcher m = pattern.matcher(string); 
int pos = 0; 
while (m.find()) 
{ 
    if (pos != m.start()) 
    { 
     res.add(string.substring(pos, m.start())) 
    } 
    res.add(m.group()) 
    pos = m.end(); 
} 
if (pos != string.length()) 
{ 
    addToTokens(res, string.substring(pos)); 
} 
for(String s : res) 
{ 
    System.out.println(s); 
} 

Output:

2 
! 
+ 
atan2 
(
3 
+ 
9 
, 
2 
+ 
3 
) 
- 
2 
* 
PI 
+ 
3 
/
3 
- 
9 
- 
12 
% 
3 
* 
sin 
(
9 
- 
9 
) 
+ 
(
2 
+ 
6 
/
2 
) 

Vấn đề là bây giờ biểu có thể chứa Matrix với định dạng người dùng xác định. Tôi muốn xem mọi Ma trận là Toán tử hoặc Đối số trong trường hợp chức năng.

Input 1:

String input_1 = "2+3-9*[{2+3,2,6},{7,2+3,2+3i}]+9*6" 

Output nên là:

2 
+ 
3 
- 
9 
* 
[{2+3,2,6},{7,2+3,2+3i}] 
+ 
9 
* 
6 

Input 2:

String input_2 = "{[2,5][9/8,func(2+3)]}+9*8/5" 

Output nên là:

{[2,5][9/8,func(2+3)]} 
+ 
9 
* 
8 
/
5 

Input 3:

String input_3 = "<[2,9,2.36][2,3,2!]>*<[2,3,9][23+9*8/8,2,3]>" 

Output nên là:

<[2,9,2.36][2,3,2!]> 
* 
<[2,3,9][23+9*8/8,2,3]> 

Tôi muốn mà bây giờ ArrayList nên chứa tất cả các toán hạng, khai thác, luận cứ, chức năng và biểu tượng ở mỗi chỉ số. Làm thế nào tôi có thể đạt được sản lượng mong muốn của tôi bằng cách sử dụng biểu thức chính quy. Xác nhận biểu thức là không bắt buộc.

+2

@trashgod tôi nghĩ rằng liên kết bạn cung cấp không liên quan đến vấn đề của tôi –

Trả lời

1

Tôi nghĩ rằng bạn có thể thử với một cái gì đó như:

(?<matrix>(?:\[[^\]]+\])|(?:<[^>]+>)|(?:\{[^\}]+\}))|(?<function>\w+(?=\())|(\d+[eE][-+]\d+)|(?<operand>\w+)|(?<operator>[-+\/*%])|(?<symbol>.) 

DEMO

yếu tố này được chụp trong nhóm chụp được đặt tên. Nếu bạn không cần đến nó, bạn có thể sử dụng ngắn hạn:

\[[^\]]+\]|<[^>]+>|\{[^\}]+\}|\d+[eE][-+]\d+|\w+(?=\()|\w+|[-+\/*%]|. 


Việc mở khung \[[^\]]+\]|<[^>]+>|\{[^\}]+\} trận đấu ({, [ hoặc <), các ký tự không clasing khung và khung đóng (}, ], >) vì vậy nếu không có dấu ngoặc đơn cùng loại, thì không có vấn đề gì. Implementatin trong Java:

public class Test { 
    public static void main(String[] args) { 
     String[] expressions = {"2!+atan2(3+9,2+3)-2*PI+3/3-9-12%3*sin(9-9)+(2+6/2)", "2+3-9*[{2+3,2,6},{7,2+3,2+3i}]+9*6", 
     "{[2,5][9/8,func(2+3)]}+9*8/5","<[2,9,2.36][2,3,2!]>*<[2,3,9][23 + 9 * 8/8, 2, 3]>"}; 
     Pattern pattern = Pattern.compile("(?<matrix>(?:\\[[^]]+])|(?:<[^>]+>)|(?:\\{[^}]+}))|(?<function>\\w+(?=\\())|(?<operand>\\w+)|(?<operator>[-+/*%])|(?<symbol>.)"); 
     for(String expression : expressions) { 
      List<String> elements = new ArrayList<String>(); 
      Matcher matcher = pattern.matcher(expression); 
      while (matcher.find()) { 
       elements.add(matcher.group()); 
      } 
      for (String element : elements) { 
       System.out.println(element); 
      } 
      System.out.println("\n\n\n"); 
     } 
    } 
} 

Giải thích về lựa chọn thay thế:

  • \[[^\]]+\]|<[^>]+>|\{[^\}]+\} - trận mở màn khung cho loại, nhân vật mà không được đóng khung của loại (tất cả mọi thứ byt không đóng khung) và khung đóng của loại ,
  • \d+[eE][-+]\d+ = chữ số này, theo sau là e hoặc E, tiếp theo là nhà điều hành + hoặc -, tiếp theo là chữ số, để nắm bắt các yếu tố như 2e+3
  • \w+(?=\() - phù hợp với một hoặc nhiều ký tự chữ (A-Za-z0-9_) nếu nó được tiếp theo ( cho phù hợp với các chức năng như sin,
  • \w+ - phù hợp với một hoặc nhiều ký tự từ (A-Za-z0-9_) để khớp với toán hạng,
  • [-+\/*%] - khớp một ký tự từ lớp ký tự, để khớp với toán tử
  • . - phù hợp với bất kỳ ký tự khác, để phù hợp với biểu tượng khác

Trình tự lựa chọn thay thế là khá quan trọng, vì cuối cùng thay thế . sẽ phù hợp với bất kỳ ký tự, vì vậy nó cần phải được lựa chọn cuối cùng. Trường hợp tương tự với \w+(?=\()\w+, thứ hai sẽ khớp với mọi thứ như trước đó, tuy nhiên nếu bạn không muốn phân biệt giữa các hàm và toán hạng, thì \w+ sẽ là đủ cho tất cả chúng.

Trong còn dụ phần (?<name> ...) trong mọi thay thế, là một nhóm chụp được đặt tên, và bạn có thể thấy trong bản demo, làm thế nào nó nhóm xuất hiện mảnh vỡ trong gorups như: toán hạng, nhà điều hành, chức năng, vv

+0

Cảm ơn bạn rất nhiều. Làm việc như quyến rũ. Như tôi đã nói rằng tôi yếu về sự hiểu biết regex vì vậy hãy cho tôi biết những gì đang xảy ra ở đây. –

+0

@KamilMahmood Tôi cập nhật câu trả lời, nếu không đủ rõ ràng, hãy tự do hỏi –

+0

Những số này 2e-3, 2e + 3, 2E-3 và 2E + 3 không được xử lý đúng và mục đích của biểu tượng XOR là gì?^". –

2

Với cụm từ thông dụng, bạn không thể khớp với bất kỳ mức ngoặc đơn cân bằng lồng nhau nào.

Ví dụ, trong ví dụ thứ hai {[2,5][9/8,func(2+3)]} bạn cần phải khớp với dấu ngoặc mở với dấu ngoặc ôm gần, nhưng bạn cần phải theo dõi xem có bao nhiêu mở và đóng dấu ngoặc ôm/parens/etc. Điều đó không thể được thực hiện với các biểu thức thông thường.

Nếu, mặt khác, bạn đơn giản hóa vấn đề của mình để loại bỏ bất kỳ yêu cầu nào để cân bằng, thì bạn có thể xử lý bằng các biểu thức chính quy.

+0

Có thể tôi nói từ bắt đầu từ điều này và kết thúc tại đây và khớp với bất kỳ thứ gì ở giữa không? –

+0

Không chắc chắn tôi theo dõi. Nếu bạn muốn kết hợp bất kỳ thứ gì giữa dấu ngoặc mở đầu tiên và dấu ngoặc đóng cuối cùng, bạn có thể làm như thế này (chưa được kiểm tra): '\ ((. *) \)' parens bên trong sẽ là thứ bạn muốn. –

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