0

I have this representative code in Javascript:

    NameRegEx = /\w+ \w+ (".*?"|\S+) (".*?"|\S+)/;
    term = NameRegEx.exec("add cmd item configname AAA 10.0.0.1 80 -option NONE -option2 YES -Option3 180");

This works and "term" is an array that contains:

0: "add cmd item configname"
1: "item"
2: "configname"

I haven't been able to find an equivalent to the exec function in Python, and would appreciate some assistance! I have a number of similar RegEx commands I also need to convert, so I need a close Python alternative.

EDIT: This is NOT the same as the linked duplicates as they did not address the fact of how the values returned were different. However Pushpesh Kumar Rajwanshi's addressed that issue with the below modification to the regex and below explanation:

s = 'add cmd item configname AAA 10.0.0.1 80 -option NONE -option2 YES -Option3 180'
arr = [s for s in re.findall(r'(\w+ \w+ (".*?"|\S+) (".*?"|\S+))',s)[0]]
print(arr)

Yes, that additional parenthesis was needed because you wanted full string to be captured as well in the array results. Otherwise findall just includes the results for ONLY groups and in case there is no group then whole match.

Reopened, because questions, linked as duplicates, do not fully address the problem.

Mikhail Vladimirov
  • 12,571
  • 1
  • 31
  • 34
KyferEz
  • 197
  • 1
  • 1
  • 11
  • https://docs.python.org/2/howto/regex.html – 41686d6564 Mar 22 '19 at 18:03
  • I think `re.findall` does a similar job if not identical and can find you the results like Javascript's `exec` did – Pushpesh Kumar Rajwanshi Mar 22 '19 at 18:06
  • `re.search` does it. – Wiktor Stribiżew Mar 22 '19 at 18:07
  • 1
    Try this Python code `import re s = 'add cmd item configname AAA 10.0.0.1 80 -option NONE -option2 YES -Option3 180' arr = [s for s in re.findall(r'(\w+ \w+ (".*?"|\S+) (".*?"|\S+))',s)[0]] print(arr)` Which prints this array `['add cmd item configname', 'item', 'configname']` – Pushpesh Kumar Rajwanshi Mar 22 '19 at 18:10
  • 1
    @PushpeshKumarRajwanshi THANK YOU! Please add this as an answer and I will accept it. The addition of the parenthesis in the regex did the trick! – KyferEz Mar 22 '19 at 18:16
  • 1
    @KyferEz: Yes, that additional parenthesis was needed because you wanted full string to be captured as well in the array results. Otherwise `findall` just includes the results for ONLY groups and in case there is no group then whole match. This post has been already marked as duplicate so can't add as answer but I'm happy I could help you :) – Pushpesh Kumar Rajwanshi Mar 22 '19 at 18:20
  • @AhmedAbdelhameed Might be a duplicate however none of those duplicates answered my question and PushpeshKumarRajwanshi identified the issue where your link was totally unhelpful and I don't appreciate this being marked as a duplicate when he should get credit. – KyferEz Mar 22 '19 at 18:20
  • @WiktorStribiżew Actually re.search does not return the results as I needed them. PushpeshKumarRajwanshi identified the issue and provided a correct and helpful answer. – KyferEz Mar 22 '19 at 18:22
  • No, `/\w+ \w+ (".*?"|\S+) (".*?"|\S+)/` with `exec` in JS returns the first match object that contains the 1) whole match, 2) Group 1, 3) Group 2, etc. It is the equivalent of `re.search`. `re.findall` extracts all captures if defined in the pattern, else, all matches. – Wiktor Stribiżew Mar 22 '19 at 18:24
  • 1
    @WiktorStribiżew: `exec` in Javascript returns an array of matches containing full match and subsequently grouped matches. OP wanted a similar function which when used can return the result as array, exactly as `exec` would have done and Python's `re.search` returns a match object and one would have to manually construct the array using match object. Where as `re.findall` can relatively do it more easily and hence is closer to `exec` function in JS. – Pushpesh Kumar Rajwanshi Mar 22 '19 at 18:39
  • @PushpeshKumarRajwanshi `exec` with a regex having no `g` modifier can only return a **single** match. You confuse *match* and *group* notions. – Wiktor Stribiżew Mar 22 '19 at 18:45
  • 1
    @WiktorStribiżew: OP indeed wanted to get the single (first) match only, if you see the post above, which is why I too used zeroth `[0]` element of `findall` result in my code posted in above comments. I know `exec` can be iterated in a loop to find all possible match results but OP seemed to be interested in the first match only. Which is also, why I wrote in my first comment that **`findall` does a similar job if not identical.** – Pushpesh Kumar Rajwanshi Mar 22 '19 at 18:49
  • @KyferEz Do not use `re.findall` to find the first match only, it is not efficient. See [this Python demo](https://ideone.com/Uei9Dx) with the right method, `re.search`. – Wiktor Stribiżew Mar 22 '19 at 19:10
  • You need something like `re.compile ("\w+ \w+ (\".*?\"|\S+) (".*?"|\S+)").search ("...").group (0, 1, 2)`. – Mikhail Vladimirov Mar 22 '19 at 20:59
  • @WiktorStribiżew I specifically needed all 3 items returned for my code, NOT just the first item, which is why I specifically stated the original JS code returned all 3 items. – KyferEz Mar 22 '19 at 21:06
  • Sure, that is where `re.search` comes in and does exactly the same as `/regex/.exec(string)` in JS. – Wiktor Stribiżew Mar 22 '19 at 21:07
  • @WiktorStribiżew Not the way I wanted. I like how clean Pushpesh's solution was. – KyferEz Mar 22 '19 at 21:08
  • Getting all matches and then only accessing the first one is not clean. – Wiktor Stribiżew Mar 22 '19 at 21:10
  • 1
    @PushpeshKumarRajwanshi the question has been reopened; you may answer now if you like. – KyferEz Mar 22 '19 at 21:10
  • @WiktorStribiżew I understand what you are saying. But you don't know my end code. It was better with his solution. – KyferEz Mar 22 '19 at 21:11

1 Answers1

1

Firstly, thank you everyone who all agreed that this post should be reopened as linked posts didn't help OP for what he was looking for.

And while answering, my primary intention was to keep the solution close to exec function call in JS (and not the performance which of course would be better for search rather than findall as the later does more work than needed but uses only first element in array), and as exec function in JS returns an array of results, a similar function in Python that returned results like array was findall.

Just like OP's regex /\w+ \w+ (".*?"|\S+) (".*?"|\S+)/ in JS didn't had global flag ON, which means he was only interested in the first match only, I used first element [0] of findall result where my Python code solution was this,

import re
s = 'add cmd item configname AAA 10.0.0.1 80 -option NONE -option2 YES -Option3 180'
arr = [s for s in re.findall(r'(\w+ \w+ (".*?"|\S+) (".*?"|\S+))', s)[0]]
print(arr)

Which printed,

['add cmd item configname', 'item', 'configname']

But the same can also be achieved by search function too and since it searches iteratively one by one, hence it will be better than findall since findall finds all possible results by scanning whole string in one operation unlike search but uses only first by accessing first element in array. Hence posting a solution using search function too similar to findall which can also be used by OP and will perform better as this will only look for first match only. Since groups() returns a tuple but OP wanted an array, hence this code is needed so OP can get the results in array exactly as he wanted as returned by exec method in JS.

import re
s = 'add cmd item configname AAA 10.0.0.1 80 -option NONE -option2 YES -Option3 180'
m = re.search(r'(\w+ \w+ (".*?"|\S+) (".*?"|\S+))', s)
if (m):
 arr = [s for s in m.groups()]
 print(arr)

Prints,

['add cmd item configname', 'item', 'configname']

But yes, one change was needed in the regex from JS that enclose the whole regex into an extra parenthesis without which it would have not given the results OP was looking for.

You can actually create a function exec in Python to mimic it from JS somewhat like this,

import re

def exec(regex, s):
 m = re.search(regex, s)
 if (m):
  return [s for s in m.groups()]


arr = exec(r'(\w+ \w+ (".*?"|\S+) (".*?"|\S+))', 'add cmd item configname AAA 10.0.0.1 80 -option NONE -option2 YES -Option3 180')
print(arr)

Which also gives same output and is reusable hence good way of doing things,

['add cmd item configname', 'item', 'configname']

At last, I am glad that through a healthy debate through comments, OP could get a working solution for the problem.

If you face any issues anytime or have any queries, please feel free to let me know.

Pushpesh Kumar Rajwanshi
  • 17,850
  • 2
  • 16
  • 35