LinuxQuestions.org
Visit the LQ Articles and Editorials section
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-16-2012, 03:53 PM   #1
mrm5102
Member
 
Registered: Apr 2011
Location: Philadelphia
Posts: 154

Rep: Reputation: 3
Bash Version 3.1 to 3.2 and Later --- Inconsistent Pattern Matching


Hello All,

I created a script that starts/stops a program on a couple different servers.

The server I wrote the script on has Bash Version 3.2.51(1)-release, and there are
a couple of different servers where the version is 3.1... and possibly some after version 3.

The problem I'm running into is this line below:
Code:
	if [[ ! $@ =~ start|stop|restart|status|help ]]
	 then
		echo "Error(1): No option given for start|stop|restart|status"
		exit 1
	fi
Now this line works just fine on the server I wrote it on, but on another server I tested it on with
Bash Version 3.1.17 I get this error for that line:
Code:
./test_script: line 51: syntax error in conditional expression: unexpected token `|'
./test_script: line 51: syntax error near `|s'
./test_script: line 51: `	if [[ ! $@ =~ start|stop|restart|status|help ]]'
So if I change the code on the older Bash Version Server, and I surround the pattern in either single or double quotes, the script executes without a hitch. But if I add that to the one with the newer Bash Version it reads the pattern as a literal string instead of a pattern. I've also tried surrounding the pattern in backslashes "/". Which works on the newer Bash Version, but again, not on the older one...?

Does anyone know of anyway I can express this where it would be compatible on both versions and possible even newer versions of Bash?


Any thoughts would be much appreciated.

Thanks in Advance,
Matt
 
Old 07-16-2012, 05:36 PM   #2
Kenhelm
Member
 
Registered: Mar 2008
Location: N. W. England
Distribution: Mandriva
Posts: 329

Rep: Reputation: 140Reputation: 140
Try putting the pattern into a variable.
Code:
pattern='start|stop|restart|status|help'
if [[ ! $@ =~ $pattern ]]
Bash pitfall number 35
http://mywiki.wooledge.org/BashPitfa...e_RE.27_.5D.5D
Quote:
35. if [[ $foo =~ 'some RE' ]]
The quotes around the right-hand side of the =~ operator cause it to become a string, rather than a RegularExpression. If you want to use a long or complicated regular expression and avoid lots of backslash escaping, put it in a variable:

re='some RE'
if [[ $foo =~ $re ]]

This also works around the difference in how =~ works across different versions of bash. Using a variable avoids some nasty and subtle problems.
Advanced Bash-Scripting Guide 37.2.2. Bash, version 3.2
http://www.tldp.org/LDP/abs/html/bas...#REGEXMATCHREF
Quote:
The =~ Regular Expression match operator no longer requires quoting of the pattern within [[ ... ]].
In fact, quoting in this context is not advisable as it may cause regex evaluation to fail. Chet Ramey states in the Bash FAQ that quoting explicitly disables regex evaluation. See also the Ubuntu Bug List and Wikinerds on Bash syntax.

Setting shopt -s compat31 in a script causes reversion to the original behavior.
 
1 members found this post helpful.
Old 07-16-2012, 09:05 PM   #3
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,425

Rep: Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876
I agree with the variable option for anything other than a simple text comparison. It is interesting that the link provided by Kenhelm also states:
Quote:
# NOTE: As of version 3.2 of Bash, expression to match no longer quoted.
Which would imply that you could still quote if needed, but the quote by Kenhelm is further down the page so I am guessing should really be used as an addendum.
 
1 members found this post helpful.
Old 07-16-2012, 11:54 PM   #4
patrick295767
Member
 
Registered: Feb 2006
Distribution: Debian
Posts: 275

Rep: Reputation: 39
Quote:
Originally Posted by mrm5102 View Post
Hello All,

I created a script that starts/stops a program on a couple different servers.

The server I wrote the script on has Bash Version 3.2.51(1)-release, and there are
a couple of different servers where the version is 3.1... and possibly some after version 3.

The problem I'm running into is this line below:
Code:
	if [[ ! $@ =~ start|stop|restart|status|help ]]
	 then
		echo "Error(1): No option given for start|stop|restart|status"
		exit 1
	fi
Now this line works just fine on the server I wrote it on, but on another server I tested it on with
Bash Version 3.1.17 I get this error for that line:
Code:
./test_script: line 51: syntax error in conditional expression: unexpected token `|'
./test_script: line 51: syntax error near `|s'
./test_script: line 51: `	if [[ ! $@ =~ start|stop|restart|status|help ]]'
So if I change the code on the older Bash Version Server, and I surround the pattern in either single or double quotes, the script executes without a hitch. But if I add that to the one with the newer Bash Version it reads the pattern as a literal string instead of a pattern. I've also tried surrounding the pattern in backslashes "/". Which works on the newer Bash Version, but again, not on the older one...?

Does anyone know of anyway I can express this where it would be compatible on both versions and possible even newer versions of Bash?


Any thoughts would be much appreciated.

Thanks in Advance,
Matt
WHich distro is it?

I hope that it is not debian testing, because, if it is a bug I am not so sure we get it fixed on time for the stable release
 
Old 07-17-2012, 03:04 AM   #5
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,425

Rep: Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876
I doubt any copy of Debian is still languishing back with bash 2.05 (could be wrong of course)
 
Old 07-17-2012, 03:25 AM   #6
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,749

Rep: Reputation: 461Reputation: 461Reputation: 461Reputation: 461Reputation: 461
Code:
 case $@ in
  start|stop|restart|status|help) : ;;
  *) echo "Error(1): No option given for start|stop|restart|status"
  exit 1
  ;;
esac
That should work for any bash version from 2 to 4.

Last edited by gnashley; 07-17-2012 at 03:27 AM.
 
1 members found this post helpful.
Old 07-17-2012, 08:27 AM   #7
mrm5102
Member
 
Registered: Apr 2011
Location: Philadelphia
Posts: 154

Original Poster
Rep: Reputation: 3
Hey Guys, thanks for all your replies!

Ahh Yes putting it in a variable.... I'll give that a go and see what happens, don't know why I didn't think of that.

Also, for those who asked about the distro. Most of the servers I am going to put this on are SLES 11.1 and some back as far as Version 10.1...
The one server that I first tried this on was a "SuSE Linux Enterprise Server v10.2" with Bash version of 3.1.17(1).

I'm gona give your suggestions a try and post back my results.
Thanks again for ALL your suggestions.


Thanks,
Matt
 
Old 07-17-2012, 08:45 AM   #8
mrm5102
Member
 
Registered: Apr 2011
Location: Philadelphia
Posts: 154

Original Poster
Rep: Reputation: 3
Hey... Thanks everybody, That worked perfectly!

I tried it on 3 different servers with 3 different Bash version from 3.1 to 4.1.10 and all seems gooood...

Is putting patterns into variables a "more" preferred way to do that then how I was doing it in my OP?


Thanks Again,
Matt
 
Old 07-17-2012, 12:36 PM   #9
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,425

Rep: Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876Reputation: 1876
The variable just allows you to update away from the test and also seems to work more often than not if the match is more complex than a straight string match.
 
Old 07-17-2012, 12:47 PM   #10
silendo
Member
 
Registered: Jun 2012
Location: Italy
Distribution: Slackware 13.37
Posts: 45

Rep: Reputation: Disabled
Code:
case $@ in
  start|stop|restart|status|help) : ;;
  *) echo "Error(1): No option given for start|stop|restart|status"
  exit 1
  ;;
esac
gnashley: i agree with you
 
Old 07-17-2012, 02:00 PM   #11
mrm5102
Member
 
Registered: Apr 2011
Location: Philadelphia
Posts: 154

Original Poster
Rep: Reputation: 3
Hey grail, thanks for the reply...

Thank you for the explanation.


Thanks Again,
Matt
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
Bash: Pattern matchin - how to do matching on a variable? SQADude Programming 23 12-09-2009 01:47 AM
Pattern matching in a bash case statement using regex ciphyre Programming 1 01-31-2009 12:20 PM
Pattern matching in BASH. ccin1492 Programming 8 12-19-2008 11:00 AM
bash script pattern matching thedude2010 Programming 9 06-02-2006 02:39 AM
Pattern Matching Help in Bash script cmfarley19 Programming 1 04-07-2004 09:22 AM


All times are GMT -5. The time now is 09:26 PM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration