Scripts works fine in CentOS but not on RHEL5 - linux

Below script works fine on CentOS but not on RHEL5:
#!/bin/bash
read -p "enter your value:" ip
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
then
echo "valid"
else
echo "invalid"
fi
Run the script and just pass 192.16666 as input, it will say valid. But if you do the same in CentOS, it will say invalid.
Please let me know what is getting wrong.
Thanks

=~ matching was introduced in Bash 3.0-alpha. The =~ semantics changed in 3.2, but it seems that was only to force text matching for right-hand quoted strings, which is irrelevant for this case. Is the version older than that?

Solved it myself by adding single quotes to the regex, as:
#!/bin/bash
read -p "enter your value:" ip
if [[ $ip =~ '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' ]]
then
echo "valid"
else
echo "invalid"
fi
Thanks bdw :)

Related

Error when checking for substring in Bash

I'm quite new to shell scripting and have encountered an issue when trying to check for substrings within a string.
I want to build code that checks if you are running a 64bit-based system. This is indicated by the output of the uname -m && cat /etc/*release command by the x86_64 in the first line.
Here's my code:
INFO=$(uname -m && cat /etc/*release)
if [ "$INFO" == *"x86_64"* ]
then
echo "You are running a 64bit-based system!"
else
echo "Your system architecture is wrong!"
exit
fi
Although I run a 64-bit based system and the x86_64 shows up in the output of my command, the if statement still returns false, so I get the output Your system architecture is wrong!. It should be the opposite.
Can someone help me out by identifying what I did wrong? I also accept general suggestions for improving my approach, but in the first place, I'd like to know where the bug is.
Many thanks for your help!
[
The command [ is equivalent to test command. test doesn't support any kind of advanced matching. test can compare strings with = - comparing strings with == in test is a bash extension.
By doing:
[ "$INFO" == *"x86_64"* ]
You are actually running command like [ "$INFO" == <the list of files that match"x86_64"pattern> ] - the *"x86_64"* undergoes filename expansion. If you would have a file named something_x86_64_something it would be placed there, the same way cat *"x86_64"* would work.
The bash extensions [[ command supports pattern matching. Do:
if [[ "$INFO" == *"x86_64"* ]]
For portable scripting that will always work with any kind of posix shell use case:
case "$INFO" in
*x86_64*) echo yes; ;;
*) echo no; ;;
esac
With bash version >= 3 you can use a regex:
[[ "$INFO" =~ x86_64 ]]
Unsure why it's so but your code starts working after doubling the square brackets:
INFO=$(uname -m && cat /etc/*release)
if [[ "$INFO" = *x86_64* ]]
then
echo "You are running a 64bit-based system!"
else
echo "Your system architecture is wrong!"
exit
fi
Perhaps some explanation can be found under Is double square brackets [[ ]] preferable over single square brackets [ ] in Bash? and alikes.
One way to check 64 bit is to simply grep the output of /bin/arch
if /bin/arch | grep -q x86_64
then
echo "it is 64 bit"
else
echo "it is not"
fi

Does not work to execute command in double brackets in bash

In an attempt to stay consistent i have tried to use double brackets [[ ]] in all my if statements. I did however get into a problem when i was going to check the return value for a command i wanted to run. After testing several ways of creating an if statement i found that only without brackets could i execute a command.
The following does not work:
if [[ $command ]] ; then
echo "something"
fi
if [[ $(command) ]] ; then
echo "something"
fi
if [[ ${command} ]] ; then
echo "something"
fi
and the code above makes the if loop true even when the command was not run.
since the code above doesnt work with braces it doesnt work to use this either:
[[ $command ]] || echo "failed"
and it doesnt work in a subshell either.
The following works:
if $command ; then
echo "something"
fi
if $(command) ; then
echo "something"
fi
Why doesnt it work to place a command in an if loop with brackets, and why does the if loops above report true when it didnt even run the command ? I'm using bash version 4.1.9. Ive tried this many times and the if loops are just as simple as the ones i typed above, it just checks if a command was run successfully and exits if it wasnt.
The short answer is:
[ and [[ expect an expression.
if expects a command.
Saying:
[[ $(command) ]]
would essentially execute:
[[ -n <command_output> ]]
which may or may not be what you want. On the other hand, saying:
$command && echo something || echo other
would echo something or other based on the return code of the command (0 and non-zero respectively).
Double braces are a shortcut for test. In your examples, what's happening is that you're testing the shell variable $command for existence.
if [[ $PWD ]]; then
echo PWD is set to a value
fi
if [[ $NOT_A_REAL_VAR ]]; then
echo Nope, its not set
fi
In your second example, you're using command substitution to check that command output something on standard output.
if [[ $(echo hi) ]]; then
echo "echo said hi'
fi
if [[ $(true) ]]; then #true is a program that just quits with successful exit status
echo "This shouldn't execute"
fi
Your third example is the same as your first, pretty much. You use the curly braces if you want to group your variables. for example if you want to put an 's' after something.
WORD=Bike
echo "$WORDS" #won't work because "WORDS" isn't a variable
echo "${WORD}S" # will output "BikeS"
Then in your fifth example, you are running the program that is sitting inside command.
So, if you want to test some strings, use [[ ]] or [ ]. If you just want to test the exit status of a program, then don't use those, just use a bare if.
Check man test for details on the braces.
If you're just checking the return value of the command, drop the double brackets.
if $command
then
echo "Command succeeded"
else
echo "Command failed: $!"
fi
The double brackets are a test command. (Well, not really, but their a takeoff of the single square brackets that were an alias to the test command.) In early Bourne shell, you would see things like:
if test -z "$string"
then
echo "This is an empty string"
fi
The square brackets were syntactic sugar:
if [ -z "$string" ]
then
echo "This is an empty string"
fi
So, if you're not doing an actual test, you can eliminate the double or single square brackets.
If you're using square brackets, you should use the double ones and not the single ones because the double ones are a bit more forgiving and can do a bit more:
if [ -z $string ] # No quotes: This will actually fail if string is zero bytes!
if [[ -z $string ]] # This will work despite the lack of quotes

Bash If Statement - Giving up hope

I have tried and tried to solve this and with my limited knowledge of BASH i cannot, I have searched but cannot find anything relating to my issue.
COMMAND_WAIT=$(curl --data "SERIAL_NUMBER="$SERIALNUMBER"" h**p://SERVER/device_check_in.php)
echo $COMMAND
if [ "$COMMAND_WAIT" == "REBOOT" ]; then
echo "Reboot Scheduled"
else
echo "Nothing Found"
fi
I have included an echo command of "COMMAND_WAIT" and this displays "REBOOT" as expected but the if statement will just not work?
Try echoing
echo ">>$COMMAND_WAIT<<"
and see if you have any padding. That might be the culprit.
I prefer to use [[]] instead of [] since [ is a builtin (a command) while [[ is a keyword (see bash manual for more details).
if [[ "$VAR" == "VALUE" ]]
then
echo "true";
else
echo "false";
fi
If it's trailling whitespaces, there's many way to skin that cat like suggested here

Linux Find Binary File

I am attempting to find a binary file in a Linux system using something like this:
if [ -f `which $1` ] then
echo "File Found"
else
echo "File not Found"
fi
while the code works fine the problem is "which" will return a null operator which BASH interprets as something existing so a file always comes back found. Any suggestions would be great.
Thanks
Update
After a bit more thought, there is no reason to use [[ ]] (or [ ] for that matter). There is even no reason to use command substitution either $()
if which "$1" > /dev/null 2>&1; then
echo "found"
else
echo "not found"
fi
If you're using bash then please use the [[ ]] construct. One of the benefits (among many) is that it doesn't have this problem
[[ -f $(which $1) ]] && echo found
Also, `` is deprecated, use $() instead
if [ `which "$1"` != "" ]; then
which won't return "" when it finds the binary.
I like 'hash' for this (if you're a bash user..) (and it's actually more portable behavior than which)
hash blahblah
bash: hash: lklkj: not found
hash /bin/ls <-- silently successful
This method works on Linux and OSX similarly, where-as 'which' has different behavior.

Check if a string contains Asterisk (*)

I want to check if my string contain one or more asterisk.
I have tried this :
if [[ $date_alarm =~ .*\*.* ]]
then
...
fi
It worked when I launch directly the script, but not if this script is called during shutdown (script installed in run level 0 and 6 via update-rc.d)
Any idea, suggestion ?
Thanks
Always quote strings.
To check if the string $date_alarm contains an asterisk, you can do:
if echo x"$date_alarm" | grep '*' > /dev/null; then
...
fi
what happens if you replace
if [[ $date_alarm =~ .*\*.* ]]
with
if [[ "$date_alarm" =~ .*\*.* ]]
you might also want to try:
if [[ "$date_alarm" =~ '\*+' ]]
not sure about that one...
regards
case "$date_alarm" in
*\**)
...
break
;;
*)
# else part
...
;;
esac
The syntax is, well, /bin/sh, but it works.
expr "$date_alarm" : ".*\*.*"
if echo $date_alarm|perl -e '$_=<>;exit(!/\*/)'
then
...
fi
Finally
if echo x"$date_alarm" | grep '*' > /dev/null; then
did the trick
Strange thing =~ .*. doesn't work only in init context during shutdown, but work perfectly if launch in bash context....
No need to redirect stdout like others do. Use the -q option of grep instead:
if echo x"$date_alarm" | grep -q '*' ; then

Resources