LinuxQuestions.org
Visit Jeremy's Blog.
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 07-20-2018, 12:57 PM   #1
cuintilo
LQ Newbie
 
Registered: Jun 2018
Distribution: Debian stretch
Posts: 14

Rep: Reputation: 0
Getting test function to work with regex in bash


Well, after having been stuck with this a couple hours now I decided to ask some help.

I'm currently reading The Linux Command Line and when I tried to do practice (chapter 28) which the book recommended I got stuck with series of errors resulting from bad syntax I can't seem to get rid of.

I have a set of small functions/programs which I'm trying to just rewrite with (worse, judging by few comments I found from web) different syntax.

Book has this:

Code:
 if [[ "$int" =~ ^-?[0-9]+$ ]];
which I'm trying to write with older version, test-function.

Book gives a hint to use grep as evaluator, but since I can't get this evaluation to work without it I haven't went that far yet.

If I want to rewrite it with test-function, do I have to use test with expr or is it just something along the lines of "test $foo = regex_i_didnt_get_right"?

Also.. Am I being stuck with trivialities here or is this relevant in the grand scheme of things (learning Linux).

Last edited by cuintilo; 07-20-2018 at 01:01 PM.
 
Old 07-20-2018, 01:53 PM   #2
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: Rocky Linux
Posts: 4,776

Rep: Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212
The legacy test command, or its alias "[", simply does not do regex. I have no way to see the book, but what I presume the book is suggesting is to use either expr or grep instead of the test command and just let the if construct use that command's return code.
Code:
if grep -q '^-?[0-9]+$' <<<$int

if expr "$int" : '-?[0-9]+'
Note the subtle difference in the regex in the expr command. That command always treats the regex as "anchored", so the "^" and "$" anchors should not be included.
 
2 members found this post helpful.
Old 07-20-2018, 07:23 PM   #3
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,789

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
Have $int in quotes, to prevent unwanted expansions.
The ? and + repeaters are defined in ERE only, that is egrep or grep -E
Code:
if egrep -q '^-?[0-9]+$' <<< "$int"
If your shell does not have the <<< operator, the following is equivalent
Code:
if echo "$int" | egrep -q '^-?[0-9]+$'
expr does BRE like grep. A fix is to emulate the ? and + with \{m,n\}.
Further, expr is vulnerable e.g. if $int contains an expr operator like ":".
A fix is to prepend a simple character, here X, on both sides of the : operator.
Code:
if expr X"$int" : X'-\{0,1\}[0-9]\{1,\}'
The BRE after the : operator works from the beginning so the ^ can be omitted.
 
1 members found this post helpful.
Old 07-21-2018, 12:32 AM   #4
cuintilo
LQ Newbie
 
Registered: Jun 2018
Distribution: Debian stretch
Posts: 14

Original Poster
Rep: Reputation: 0
Thank you both for help/info. Especially that echo piping to grep looks like it could come in handy sometimes. Had a good nights sleep and was able to figure it out and write them in a way that didn't result in errors.

If you had to omit compounds when using conditionals which you think would be better to use, expr or grep? I find expr a bit easier to read in code, so I'd go for that if Id have to, but newer syntax seems way more convenient and easier to read.

Book was right, though... This was a good exercise. It made me read a whole lot more than what was written in the book itself.
 
Old 07-21-2018, 01:41 AM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
I would disagree about the shell not handling regex as I have used it extensively.
I have found that if you need to do as complicated regex it is best to place it in a variable.
Code:
regex='^-?[0-9]+$'

if [[ "$int" =~ $regex ]]
You will not that the "regex" parameter is unquoted, this is important
 
Old 07-21-2018, 02:52 AM   #6
cuintilo
LQ Newbie
 
Registered: Jun 2018
Distribution: Debian stretch
Posts: 14

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by grail View Post
I would disagree about the shell not handling regex as I have used it extensively.
I have found that if you need to do as complicated regex it is best to place it in a variable.
Code:
regex='^-?[0-9]+$'

if [[ "$int" =~ $regex ]]
if test '(egrep '^-?[0-9]+$' <<<"$int")'; then

You will not that the "regex" parameter is unquoted, this is important
But this is compound representation, I was asking about older version of the command which apparently doesn't do it. Would probably have to dig deeper into google search to find older documentation for that, but I'll trust information given by rcnichols that it's not supported.

Code I used to rewrite first example from the book started like this:
Code:
if test '(egrep '^-?[0-9]+$' <<<"$int")'; then
Example start was piece I mentioned at the start of thread. Suggestion to put regexes into variables is a good one though, should be common sense but I still have sometimes a habit of not using enough variables in my code. Would probably need some bigger project to really teach me the hard way...

Last edited by cuintilo; 07-21-2018 at 03:08 AM.
 
Old 07-21-2018, 07:55 AM   #7
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,789

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
Often a case-esac is an alternative.
But the ERE must be converted to a shell glob. After all the | is an OR, giving it a bit more capability.
Code:
case $int in
(?*[!0-9]*|[!-0-9]*|"")
  echo false
;;
(*)
  echo true
esac
 
  


Reply

Tags
bash



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
[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
Need with regex function in C pgpython Programming 1 03-11-2010 10:16 PM
my var in bash doesn't work: ARRAY_$a_$b="test" SlackerJack Linux - General 3 01-13-2008 03:45 AM
Bash Scripting - Using a function as test. ldp Programming 1 01-04-2005 06:31 AM
bash - ftp doesn't work within a function richie-451 Programming 3 01-31-2002 01:21 PM

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

All times are GMT -5. The time now is 09:03 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