0

I have a list of various su commands. All the commands use the full path to the su command. And the commands may or may not have a username and may or may not have the - option.

Also there maybe options and arguments after the username like /usr/bin/su aa* or /bin/su - squid * or /bin/su - mapr -c "/usr/bin/hadoop fs -mkdir /user/*".

Here is what I have tried and I didn't get very far before I ran into trouble.

for c in su_commands.all()[0:10]:
   ...:     print(c.name)
   ...:     m = re.search('/su\s*[-]\s*(\S*)', c.name).group(1)
   ...:     print(m)
   ...:     
//bin/su - audituser.gen
audituser.gen
//usr/bin/su - hradm
hradm
/apps/su - capital
capital
/apps/su - cscdm
cscdm
/apps/su - invadm
invadm
/bib/su sapbridg
Traceback (most recent call last):
  File "/apps/sfo_rcecala/sfo_rcecala/env3/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-39-788d11c0e2c2>", line 3, in <module>
    m = re.search('/su\s*[-]\s*(\S*)', c.name).group(1)
AttributeError: 'NoneType' object has no attribute 'group'

I thought that have [-] in my regex would make the - optional.


Thanks Barmar. I have updated my regex and now I am getting further.

for c in su_commands.all()[0:10]:
   ...:     print(c.name)
   ...:     m = re.search('/su\s*\-?\s*(\S*)', c.name).group(1)
   ...:     print(m)
   ...:     
//bin/su - audituser.gen
audituser.gen
//usr/bin/su - hradm
hradm
/apps/su - capital
capital
/apps/su - cscdm
cscdm
/apps/su - invadm
invadm
/bib/su sapbridg
sapbridg
/bin//su - hdpapjpa
hdpapjpa
/bin/su  oabifstg

/bin/su  xxcconx
xxcconx
/bin/su  xxswaadm
xxswaadm

But as you can see I missed the user oabifstg.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Red Cricket
  • 9,762
  • 21
  • 81
  • 166
  • 1
    Why do you think `[-]` makes it optional? The syntax to make something optional is to put `?` after it. – Barmar Jul 13 '20 at 22:24
  • @RedCricket I deleted my comment before you replied - the manual page for `su` says `su [options] [username]` but then I saw that options after the username in fact work and are included in your strings (I didn't read the question carefully enough). – alani Jul 13 '20 at 22:25
  • Are there any examples where the commands actually use options (other than just the `-`) *before* the username? That could complicate things. – alani Jul 13 '20 at 22:34
  • @alaniwi there are. like `/bin/su -l puppetadmin` – Red Cricket Jul 13 '20 at 22:38
  • @RedCricket That's going to be fun then, especially considering that some options take arguments and others don't. I wondered about splitting it up into a list and then using `argparse` just as you would if your code was actually implementing `su`... but even that will be complicated because these are shell commands and spaces inside quotes would need protecting from splitting somehow. Don't know. – alani Jul 13 '20 at 22:41

1 Answers1

1

The syntax to make something optional is to put ? after it. Square brackets are for specifying a character set, e.g. [abc] matches either a, b, or c.

Try this.

m = re.search(r'/su\s+(?:-\s+)?(\S*)', c.name).group(1)

At least one space is required after su, then - followed by spaces is an optional group.

If you want to allow arbitrary options before the username, use a repeating group that matches - followed by zero or more non-space characters.

m = re.search(r'/su\s+(?:-\S*\s+)*(\S*)', c.name).group(1)

I also used a raw string so that all the escape sequences would be processed by the re module. See this for more details.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • That regex works great. But I just realized that I have command in the list that look like this: `/bin/su -l mongod` How can I work the in the extra `l`? – Red Cricket Jul 13 '20 at 22:51
  • I've updated the answer to allow any number of options before the username. – Barmar Jul 13 '20 at 22:59