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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
05-18-2024, 03:26 AM
|
#1
|
Member
Registered: Jan 2024
Posts: 161
Rep:
|
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:
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.
|
|
|
05-18-2024, 03:51 AM
|
#2
|
Senior Member
Registered: Mar 2007
Posts: 2,204
|
Code:
MODEMNO=$(mmcli -L|sed 's_.*Modem/__;s_ .*__')
|
|
1 members found this post helpful.
|
05-18-2024, 04:57 AM
|
#3
|
Senior Member
Registered: Dec 2011
Location: Simplicity
Posts: 2,917
|
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.
|
05-18-2024, 09:43 AM
|
#4
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702
|
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.
|
05-18-2024, 11:27 AM
|
#5
|
Senior Member
Registered: Dec 2011
Location: Simplicity
Posts: 2,917
|
@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.
|
|
|
05-18-2024, 11:35 AM
|
#6
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702
|
Quote:
Originally Posted by MadeInGermany
@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.
|
|
|
05-18-2024, 12:00 PM
|
#7
|
Senior Member
Registered: Dec 2011
Location: Simplicity
Posts: 2,917
|
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.
|
05-19-2024, 02:03 AM
|
#8
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,017
|
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]##*/}"
|
|
|
05-19-2024, 02:04 AM
|
#9
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,017
|
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.
|
05-19-2024, 05:48 AM
|
#10
|
Member
Registered: Jan 2024
Posts: 161
Original Poster
Rep:
|
Quote:
Originally Posted by MadeInGermany
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.
|
|
|
05-19-2024, 06:26 AM
|
#11
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702
|
that is the + after [0-9], which means: one ore more of it
see regex quantifiers
|
|
1 members found this post helpful.
|
05-19-2024, 12:26 PM
|
#12
|
Member
Registered: Jan 2024
Posts: 161
Original Poster
Rep:
|
Quote:
Originally Posted by pan64
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.
|
|
|
05-20-2024, 01:56 AM
|
#13
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702
|
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
|
|
|
All times are GMT -5. The time now is 03:29 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|