LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-18-2024, 03:26 AM   #1
linuxuser371038
Member
 
Registered: Jan 2024
Posts: 56

Rep: Reputation: 1
Help with bash regex


Example output of mmcli -L command:

Code:
/org/freedesktop/ModemManager1/Modem/0 [QUALCOMM INCORPORATED] 0
In the script I got for checking sms from online someone had written a regex but it is not right for my new modem as it only searched 0-9 and for some reason when trying last night the modem number was into the 20s. It back down at 0 today. I think it was because I was pugging and unplugging quite a bit. So I would like to regex double digits.

Original regex line:

Code:
MODEMNO=$(mmcli -L | grep -o "Modem/[0-9]" | grep -o [0-9]$)
One I cobbled together however it produces 3 outputs:

Code:
MODEMNO=$(mmcli -L|grep -Eo '[[:digit:]]+')
The above produces several outputs, which would, if using the example output from above, be:

Code:
1
0
0
I only want the middle number. 0 in this case but factor for any any number into the double digits. It was late last night and ran out of steam. I realized I could probably simplify with using a regex which uses other parts of the string but only picking the number part. This would have been rudimentary a while ago but I have forgotten it!

I gather I could also use grouping with the existing one and choose the middle but, again, forgotten how to do groupings.

Also I read that grep is not required at all and the regex could be done right in a bash variable. I would be interested in knowing that too and just generally the simplest way but I my attention was waning last night and so stopped and posting where I got up to.


I haven't coded in about a year and it was embarrassing to notice how rusty I was. Then again bash and regex were only periphery to my main language of python.

Last edited by linuxuser371038; 05-19-2024 at 12:33 PM.
 
Old 05-18-2024, 03:51 AM   #2
Petri Kaukasoina
Senior Member
 
Registered: Mar 2007
Posts: 1,936

Rep: Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568Reputation: 1568
Code:
MODEMNO=$(mmcli -L|sed 's_.*Modem/__;s_ .*__')
 
1 members found this post helpful.
Old 05-18-2024, 04:57 AM   #3
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,832

Rep: Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219
The consequent fix on the original is:
Code:
MODEMNO=$( mmcli -L | grep -Eo "Modem/[0-9]+" | grep -Eo "[0-9]+$" )
With GNU grep -P it shrinks to
Code:
MODEMNO=$( mmcli -L | grep -Po "(?<=Modem/)[0-9]+" )
or
Code:
MODEMNO=$( mmcli -L | grep -Po "Modem/\K[0-9]+" )
With sed:
Code:
MODEMNO=$( mmcli -L | sed -nE "s#.*Modem/([0-9]+).*#\1#p" )
 
1 members found this post helpful.
Old 05-18-2024, 09:43 AM   #4
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
Code:
answer=( $(mmcli -L) )
echo ${answer##*/}
no sed, no grep, no pipe, just pure bash.
Code:
b=( $(mmcli -L) )
answer="${b[0]}"                  # interesting, it works without it too.
echo ${answer##*/}
 
1 members found this post helpful.
Old 05-18-2024, 11:27 AM   #5
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,832

Rep: Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219
@pan64,
the unquoted $(mmcli -L) tries filename generation (disable with set -f unless you know that nmcli -L never produces a wildcard).

Another (and safe) solution with bash builtins:
Code:
[[ "$( mmcli -L )" =~ Modem/([0-9]+) ]] ; MODEMNO=${BASH_REMATCH[1]}

Last edited by MadeInGermany; 05-18-2024 at 11:41 AM.
 
Old 05-18-2024, 11:35 AM   #6
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
Quote:
Originally Posted by MadeInGermany View Post
@pan64, you didn't see the text after the modem/0 ?
And what if it would contain another / character?
Also the unquoted $(mmcli -L) tries filename generation (disable with set -f unless you know that nmcli -L never produces a wildcard).

Another (and safe) solution with bash builtins:
Code:
[[ "$( mmcli -L )" =~ Modem/([0-9]+) ]] ; MODEMNO=${BASH_REMATCH[1]}
You are right, I would not accept that too. mmcli -L will list modems, () will split the output, and actually the script will just cut everything before the last / (of the first word). Using the sample by OP it works, in general it is not really safe.
If I need to vote probably I would prefer sed. Bash is not really good at regex.

Last edited by pan64; 05-18-2024 at 11:37 AM.
 
Old 05-18-2024, 12:00 PM   #7
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,832

Rep: Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219Reputation: 1219
Lately seeing that the following text is separated by whitespace, I have edited my post.
Only my point with the filename generation is valid.

I think bash uses the Posix ERE engine, while sed -E uses the ERE engine with some GNU extensions (like \s).
Bash stores the BASH_REMATCH[1] after a match-only, while sed can only use the \1 immediately, within the s command.

Last edited by MadeInGermany; 05-21-2024 at 05:29 AM.
 
1 members found this post helpful.
Old 05-19-2024, 02:03 AM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
In second example of assigning b array to answer, you could of course do the expansion in one go:
Code:
b=( $(mmcli -L) )
echo "${b[0]##*/}"
 
Old 05-19-2024, 02:04 AM   #9
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
In second example of assigning b array to answer, you could of course do the expansion in one go:
Code:
b=( $(mmcli -L) )
echo "${b[0]##*/}"
 
1 members found this post helpful.
Old 05-19-2024, 05:48 AM   #10
linuxuser371038
Member
 
Registered: Jan 2024
Posts: 56

Original Poster
Rep: Reputation: 1
Quote:
Originally Posted by MadeInGermany View Post
The consequent fix on the original is:
Code:
MODEMNO=$( mmcli -L | grep -Eo "Modem/[0-9]+" | grep -Eo "[0-9]+$" )
With GNU grep -P it shrinks to
Code:
MODEMNO=$( mmcli -L | grep -Po "(?<=Modem/)[0-9]+" )
or
Code:
MODEMNO=$( mmcli -L | grep -Po "Modem/\K[0-9]+" )
With sed:
Code:
MODEMNO=$( mmcli -L | sed -nE "s#.*Modem/([0-9]+).*#\1#p" )
You are missing the part though where I said I want between 0-99? Which is the whole impetus for wanting to change the original.

I have not tried each yet but aren't the rest also missing the part where I wanted 0-99? Since I see only single digit so far.

Apologies if some do factor this as I didn't test each one yet but have not seen it mentioned yet.

Last edited by linuxuser371038; 05-19-2024 at 05:51 AM.
 
Old 05-19-2024, 06:26 AM   #11
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
that is the + after [0-9], which means: one ore more of it
see regex quantifiers
 
1 members found this post helpful.
Old 05-19-2024, 12:26 PM   #12
linuxuser371038
Member
 
Registered: Jan 2024
Posts: 56

Original Poster
Rep: Reputation: 1
Quote:
Originally Posted by pan64 View Post
Code:
answer=( $(mmcli -L) )
echo ${answer##*/}
no sed, no grep, no pipe, just pure bash.
Code:
b=( $(mmcli -L) )
answer="${b[0]}"                  # interesting, it works without it too.
echo ${answer##*/}
Thanks, I just tried this. Clean and succinct. Could I have an explainer?

Reminds me of how in python I would try and cram loads of nested list comprehensions just for fun even if it looked unwieldy.
 
Old 05-20-2024, 01:56 AM   #13
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
what is missing?
Code:
mmcli -L             # this is your command
$( )                 # will execute the command and returns the output of it
( content*)          # will split the content into an array (which is actually the output of your command)
answer=(..)          # assign the array to the variable "answer" (or b)
answer="${b[0]}"     # assign the first element of array b to the variable answer (which is now not an array)
${answer##*/}        # remove everything from the string until the last / in the variable answer
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Confusing issue with Perl regEx - Regex check seems to require variable being set EnderX Programming 1 09-07-2013 04:36 AM
[SOLVED] differences between shell regex and php regex and perl regex and javascript and mysql golden_boy615 Linux - General 2 04-19-2011 01:10 AM
Perl to find regex and print following 5 lines after regex casperdaghost Linux - Newbie 3 08-29-2010 08:08 PM
regex with sed to process file, need help on regex dwynter Linux - Newbie 5 08-31-2007 05:10 AM
Need a regex, I suck at regex's d3funct Programming 4 02-25-2002 08:28 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:59 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration