Как проанализировать аргументы командной строки переменной длины с регулярным выражением? - PullRequest
3 голосов
/ 31 мая 2019

У меня есть большое количество файлов, каждый из которых содержит команду bash с переменным количеством параметров. Мне нужно заменить их на соответствующий вызов API.

Пример команды bash в файле (Примечание: количество аргументов '-p' может быть разным, у некоторых их нет):

./some_script.sh http://some.server.com -p a=value -p b=value -p c=value

Пример соответствующего вызова API

http://some.server.com/api/some/endpoint?a=value&b=value&c=value

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

Базовое регулярное выражение (это будет соответствовать приведенному выше примеру, но только первый параметр группы):

.\/some_script.sh\s([\w\/:\.]*)(\s-\w\s[\w=]*)

И я попробовал:

.\/some_script.sh\s([\w\/:\.]*)(\s-\w\s[\w=]*)*

Однако, похоже, это группирует только последний параметр. (проверено с помощью regex101)

В идеале, я бы хотел, чтобы это регулярное выражение могло группировать неопределенное количество аргументов в этих файлах, чтобы я мог легко перестроить команду как вызов API.

Если требуется более подробная информация, пожалуйста, дайте мне знать, любые предложения приветствуются.

Ответы [ 2 ]

2 голосов
/ 31 мая 2019

Вам необходимо использовать якорь \ G

/(?|\.\/some_script\.sh\s([\w\/:.]*)|(?!^)\G())\s-(\w)\s([\w=]*)/

https://regex101.com/r/0151qC/1

Расширенный

 (?|                           # Branch reset
      \. /some_script \. sh         # First, find the script name
      \s 
      ( [\w/:.]* )                  # (1), url

   |                              # or,
      (?! ^ )
      \G                            # Start where last left off
      ( )                           # (1), blank url

 )

 \s - 
 ( \w )                        # (2), - 'p'
 \s 
 ( [\w=]* )                    # (3), 'a=value'
1 голос
/ 31 мая 2019

Здесь, возможно, мы могли бы найти другой подход и пошагово собирать желаемые данные из наших входных данных.Тогда мы, вероятно, начнем с выражения, похожего на:

.+\.sh.+?(https?:\/\/[^\s]*)|\s+-[a-z]+\s+([\w=]+)

, которое имеет нашу ссылку здесь:

(https?:\/\/[^\s]*)

и наши переменные в:

([\w=]+)

изменены с логическим ИЛИ.

Мы также можем изменить и добавить другие границы или уменьшить наши границы, если это может быть желательным.

DEMO

Тест

Этот фрагмент показывает, как работают группы захвата:

const regex = /.+\.sh.+?(https?:\/\/[^\s]*)|\s+-[a-z]+\s+([\w=]+)/gm;
const str = `./some_script.sh http://some.server.com -p a=value -p b=value -p c=value
`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

...