Операция извлечения (...);и sub Operation из String с использованием REGEX - PullRequest
1 голос
/ 30 сентября 2019

У меня проблема с Regex в Java для Android. я хотел бы получить первую операцию (и каждую подоперацию), как в следующих примерах:

  1. "OPERATION (ASYNC_OPERATION, _RFID_ITEM_SERIAL);"
  2. "OPERATION (CONCAT, ~1261,01, OPERATION (ASYNC_OPERATION, _RFID_ITEM_ID) ;, 21, OPERATION (ASYNC_OPERATION, _RFID_ITEM_SERIAL);); "

Как вы можете видеть, каждая операция может иметь подоперации ... И вот где яУ меня проблемы.

На самом деле я использую это регулярное выражение: ^\s*(OPERATION\s*\(\s*)(.*)(\);)

, но индекс ");"return всегда является последним индексом, и в случае двух подопераций внутри операции «Main» это неверно ...

private static Pattern operationPattern=Pattern.compile("^\\s*(OPERATION\\s*\\(\\s*)(.*)(\\);)",Pattern.CASE_INSENSITIVE);

    public Operation(String text){
        parseOperationText(text);
    }

    private void parseOperationText(String text){
        String strText = text.replace("#,", "§");
        Matcher matcher=operationPattern.matcher(strText);
        if(matcher.find()) {
            //This is an OPERATION
            subOperations=new ArrayList<>();
            String strChain = matcher.group(2);//Should only contain the text between "OPERATION(" and ");"

            int commaIdx = strChain.indexOf(",");
            if (commaIdx == -1) {
                //Operation without parameter
                operationType = strChain;
            } else {
                //Operation with parameters
                operationType = strChain.substring(0, commaIdx);
                strChain = strChain.substring(commaIdx + 1);
                while (strChain.length()>0) {
                    matcher = operationPattern.matcher(strChain);
                    if (matcher.find()) {
                        String subOpText=matcher.group(0);
                        strChain=StringUtils.stripStart(strChain.substring(matcher.end())," ");
                        if(strChain.startsWith(",")){
                            strChain=strChain.substring(1);
                        }
                        subOperations.add(new Operation(subOpText));
                    }
                    else{
                        commaIdx = strChain.indexOf(",");
                        if(commaIdx==-1)
                        {
                            subOperations.add(new Operation(strChain));
                            strChain="";
                        }
                        else{
                            subOperations.add(new Operation(strChain.substring(0,commaIdx)));
                            strChain=strChain.substring(commaIdx+1);
                        }
                    }
                }
            }
        }
        else {
            //Not an operation
            //...
        }
    }

Это работает для образца 1, но для образца 2, после нахожденияОперация «Main» (в примере CONCAT), второе совпадение возвращает следующее:

OPERATION (ASYNC_OPERATION, _RFID_ITEM_ID) ;, 21, OPERATION (ASYNC_OPERATION, _RFID_ITEM_SERIAL);

Что бы я хотелкак получить это:

  1. "CONCAT, ~ 1261,01, OPERATION (ASYNC_OPERATION, _RFID_ITEM_ID) ;, 21, OPERATION (ASYNC_OPERATION, _RFID_ITEM_SERIAL);"
  2. "ASYNC_RFID_ITEM_ID "
  3. " ASYNC_OPERATION, _RFID_ITEM_SERIAL "

Ответы [ 2 ]

1 голос
/ 30 сентября 2019

Можно использовать это

"(?s)(?=OPERATION\\s*\\()(?:(?=.*?OPERATION\\s*\\((?!.*?\\1)(.*\\)(?!.*\\2).*))(?=.*?\\)(?!.*?\\2)(.*)).)+?.*?(?=\\1)(?:(?!OPERATION\\s*\\().)*(?=\\2$)"

, чтобы найти сбалансированную строку OPERATION( ) в группе 0.

https://regex101.com/r/EsaDtC/1

Затем используйтеэто

(?s)^OPERATION\((.*?)\)$

в последней соответствующей строке, чтобы получить внутреннее содержимое операции
, которая находится в группе 1.

0 голосов
/ 02 октября 2019

Наконец, я использую два разных REGEX:

//First Regex catches main operation content (Group 2):  
\s*(OPERATION\s*\(\s*)(.*)(\);) 
//Second Regex catches next full sub "OPERATION(...);" (Group 0):
^(?:\s*(OPERATION\s*\(\s*))(.*)(?:\)\s*\;\s*)(?=\,)|^(?:\s*(OPERATION\s*\(\s*))(.*)(?:\)\s*\;\s*)$ 

Затем я могу использовать Frist Regex, чтобы определить, является ли это операцией (match.find ()), перехватить его содержимое в Group (2)а затем для каждого параметра (через запятую) я могу проверить, является ли это подоперацией со вторым регулярным выражением. Если это подоперация, я рекурсивно вызываю ту же функцию, которая снова использует First Regex ... и т. Д.

    private static Pattern operationPattern=Pattern.compile("^\\s*(OPERATION\\s*\\(\\s*)(.*)(\\);)",Pattern.CASE_INSENSITIVE);
    private static Pattern subOperationPattern=Pattern.compile("^(?:\\s*(OPERATION\\s*\\(\\s*))(.*)(?:\\)\\s*\\;\\s*)(?=\\,)|^(?:\\s*(OPERATION\\s*\\(\\s*))(.*)(?:\\)\\s*\\;\\s*)$",Pattern.CASE_INSENSITIVE);

    private void parseOperationText(String strText ){
        Matcher matcher=operationPattern.matcher(strText);
        if(matcher.find()) {
            //This is an OPERATION
            subOperations=new ArrayList<>();
            String strChain = matcher.group(2);
            int commaIdx = strChain.indexOf(",");
            if (commaIdx == -1) {
                //Operation without parameter
                operationType = strChain;
            } else {
                //Operation with parameters
                operationType = strChain.substring(0, commaIdx);
                strChain = strChain.substring(commaIdx + 1);
                while (strChain.length()>0) {
                    matcher = subOperationPattern.matcher(strChain);
                    if (matcher.find()) {
                        String subOpText=matcher.group(0);
                        strChain=StringUtils.stripStart(strChain.substring(matcher.end())," ");
                        if(strChain.startsWith(",")){
                            strChain=strChain.substring(1);
                        }
                        subOperations.add(new Operation(subOpText));
                    }
                    else{
                        commaIdx = strChain.indexOf(",");
                        if(commaIdx==-1)
                        {
                            subOperations.add(new Operation(strChain));
                            strChain="";
                        }
                        else{
                            subOperations.add(new Operation(strChain.substring(0,commaIdx)));
                            strChain=strChain.substring(commaIdx+1);
                        }
                    }
                }
            }
        }
        else {
            //Fixed value: we store the value as is
            fieldValue = strText;
            operationType = OperationType.NONE;
        }
    }

public Operation(String text){
        parseOperationText(text);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...