LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 07-06-2018, 05:12 PM   #1
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Rep: Reputation: 13
bash if statement, cannot get the else


Here is an excerpt from the script.
Code:
while IFS= read -r line; do
   echo "line is $line
   if [ ! $line == "#*" ]; then
      echo "# not found"
   else
      echo "# was found"
   fi
There is a bit more in there but I cannot copy paste and I think the essence is correct. The else side of the if statement is not printing. What do I have wrong?

Edit: I made a change further up the code that should have no effect here. Now when the script runs the terminal window displays:

./find_where_each_so_is_used.sh line 93: [: too many arguments.

It puts that line on my screen twice. Line 93 is the if statement repeated here:

Code:
if [ ! $line == "#*" ]; then
I tried putting the "then" on the next line with no effect.

Last edited by bkelly; 07-06-2018 at 05:51 PM.
 
Old 07-06-2018, 05:39 PM   #2
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
Quote:
Originally Posted by bkelly View Post
Code:
if [ ! $line == "#*" ];
i am unsure about this syntax.
what are you checking for? if a line starts with a comment, or if it starts with "#*" literally?
and why is $line not in doublequotes?
which shell is it? bash or something else?
i always thought == is bash-specific, but then one would use [[...]] instead of [...].
and maybe the negator ! should be outside the square brackets? like so:
Code:
if ! [[ "$line" == "#"* ]]; then...
but then you could also use
Code:
if [[ "$line" != "#"* ]]; then...
 
Old 07-06-2018, 06:09 PM   #3
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
hello ondoho,
Well, remember this is the beginner's forum. As noted in the OP it is bash and the first line is: #!/bin/bash
The main body of the if was producing only what is desired so I did not see a need for the double quotes.
However, things went a bit funky and I added an EDIT to the OP.
Then I saw your post and put double quote as noted to make:

Quote:
if [ ! "$line" == "#*" ]; then
And that got rid of the new problem. And yes, I just want to suppress the lines that begin with the # and there is some code to do some greps that is commented out while getting the if statement right. But the else of the if is not taken and that puzzles me. And changing to [[ statement ]] made no difference.

Last edited by bkelly; 07-06-2018 at 06:10 PM.
 
Old 07-06-2018, 06:34 PM   #4
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,924

Rep: Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040
The basic rules are
single '[' single '=':
[ 'something' = "$line" ]
double '[' double '=':
[[ 'something' == "$line" ]]

Also, "#*" won't do what you think it does. You'd have to use something like
[ '#' = "${line:0:1} ]

But, for what you're looking to do a case statement might be better:
Code:
while read line
do
  case "$line" in
    #* )  : # ignore it
          ;;
    * )   echo "do something with $line" 
          ;;
  esac
done
 
Old 07-07-2018, 02:33 AM   #5
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,844

Rep: Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222
The parser for case is like [[ ]], and the pattern glob in case is like ==
So you can write the latter as
Code:
while read line
do
  if [[ "$line" == #* ]]
  then
    : # ignore it
  else
    echo "do something with $line"
  fi
done
The quotes for $line after case and after [[ are not needed, but it is never a mistake to do so.
The #* must not be in quotes in order to keep its glob meaning.
Do not mix up [[ ]] with [ ]! The latter uses the command parser where you need to quote arguments, you cannot use a glob safely, and therefore only the = operator is applicable.
--
In post#1 the first echo statement is missing the ending quote.
 
1 members found this post helpful.
Old 07-07-2018, 03:22 AM   #6
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,924

Rep: Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040
I usually use [ ] and case rather than [[ ]] for portability reasons: case provides a way of globbing for shells that don't have [[ ]]. The "unnecessary" quotes are similarly partly for portability, and partly for style.


What we both forgot to do however was escape the '#' *
Code:
$ line='# wibble' ; [[ "$line" == #* ]] && echo yes
bash: unexpected argument `newline' to conditional binary operator
bash: syntax error near `yes'
$ line='# wibble' ; [[ "$line" == \#* ]] && echo yes
yes
$

* Late night posting is my excuse... and I'm sticking to it.

Last edited by GazL; 07-07-2018 at 04:40 AM.
 
1 members found this post helpful.
Old 07-07-2018, 04:31 AM   #7
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,844

Rep: Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222
Oh yes, the # must be quoted! Otherwise the shell sees it as a comment sign.

A correction for my previous statement:
The * must not be in quotes in order to keep its glob meaning.
So it must be \#* or "#"* or '#'*

Last edited by MadeInGermany; 07-07-2018 at 04:36 AM.
 
Old 07-07-2018, 07:51 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
As a different way to attack, you could feed your while loop only the lines you want, assuming the commented lines aren't needed later?
Code:
while IFS= read -r line
do
  ...
done< <(grep -v '^#' file)
Or pass output of command to grep if coming from a stream.
 
Old 07-07-2018, 05:08 PM   #9
X-LFS-2010
Member
 
Registered: Apr 2016
Posts: 510

Rep: Reputation: 58
the correct way you see in allot of Makefile scripts (often written by experience people long ago) is:


[ c"foo" = c"$x" ] && { echo hi ; }

or

if [ c"foo" = c"$x" ] ; then flathead ; fi

why use c? there's a reason. just do it.

the above syntax is compatible with many shells (bash, zsh, ksh, tcsh). don't use just any syntax or if you buy, say a freebsd or apple imac: your scripts may all be broken

Last edited by X-LFS-2010; 07-07-2018 at 05:10 PM.
 
Old 07-07-2018, 07:10 PM   #10
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,924

Rep: Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040Reputation: 5040
Quote:
Originally Posted by X-LFS-2010 View Post
if [ c"foo" = c"$x" ] ; then flathead ; fi

why use c? there's a reason. just do it.
That practice is historical baggage that hasn't been needed for a very long time. Unless you're writing some sort of generic shell script that might end up running on god only knows what (such as ./configure scripts) then there's absolutely no point in using that hack. It's certainly pointless if you know your script will be running in bash, dash, ksh, zsh and probably every other common shell not written 40 years ago.

People keep using it because someone told them they should at some point in the past. Ask them why and they frequently won't be able to answer.
 
Old 07-07-2018, 09:12 PM   #11
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,764

Rep: Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225
bkelly,
Have you tried putting
Code:
set -x
at the top of your script to see what the if statment is actually seeing?
 
Old 07-07-2018, 09:13 PM   #12
rnturn
Senior Member
 
Registered: Jan 2003
Location: Illinois (SW Chicago 'burbs)
Distribution: openSUSE, Raspbian, Slackware. Previous: MacOS, Red Hat, Coherent, Consensys SVR4.2, Tru64, Solaris
Posts: 2,818

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
[QUOTE=bkelly;5876467]Here is an excerpt from the script.
Code:
while IFS= read -r line; do
   echo "line is $line
   if [ ! $line == "#*" ]; then
      echo "# not found"
   else
      echo "# was found"
   fi
I'm with ondoho... Did you try putting "$line" in double quotes. As a general rule, I always do string comparison with quoted strings. There's too many things that can go wrong.

Plus, you forgot to close the text in the initial "echo" statement. Probably just a snafu in making the post, though. But if it isn't, all sorts of odd errors can crop up as the shell closes the quote using a double quote from another statement. I'm not crazy about too much syntax coloring but you might try using an editor like vim. If memory serves, quoted strings are colored green (YMMV) so if you see a whole lot of green (or whatever color) where you weren't expecting it, look for a missing quote somewhere. Same thing could happen when accidentally using a brace instead of a square bracket, etc.
 
Old 07-07-2018, 09:17 PM   #13
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,764

Rep: Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225Reputation: 2225
Quote:
Originally Posted by bkelly View Post
Here is an excerpt from the script.
Code:
while IFS= read -r line; do
   echo "line is $line
   if [ ! $line == "#*" ]; then
      echo "# not found"
   else
      echo "# was found"
   fi
I, too, would expect
Code:
if [ $line != "#"* ]
(^quoting corrected) to be the correct syntax for a non-match...

Edit: See MadeInGermany's correction below re: globbing.

Last edited by scasey; 07-08-2018 at 06:18 PM.
 
Old 07-08-2018, 04:51 AM   #14
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,844

Rep: Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222Reputation: 1222
No, [ ] cannot handle wildcards safely (the shell glob-matches against the current directory unless set -f was done), and unquoted variables are expanded.
Only [[ ]] provides the robustness for * globbing and unquoted variables.
Correct is
Code:
if [[ $line != "#"* ]]
 
1 members found this post helpful.
Old 07-08-2018, 06:06 PM   #15
Shadow_7
Senior Member
 
Registered: Feb 2003
Distribution: debian
Posts: 4,137
Blog Entries: 1

Rep: Reputation: 874Reputation: 874Reputation: 874Reputation: 874Reputation: 874Reputation: 874Reputation: 874
You might try the posix variants of comparisons.

Code:
if [ "$line" -eq "#*" ]; then
  echo ewww
else
  echo ahhh
fi
You might also NOT be running bash if the shebang is #!/bin/sh.

$ ls -al $(which sh)
 
  


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
How to get some bash scripts into a simple bash script with some echo and if statement. y0_gesh Programming 3 03-01-2012 09:46 AM
Strange if statement behaviour when using bash/bash script freeindy Programming 7 08-04-2008 06:00 AM
BASH IF statement kinetik Programming 10 05-07-2006 02:48 AM
Bash: Print usage statement & exit; otherwise continue using Bash shorthand operators stefanlasiewski Programming 9 02-07-2006 05:20 PM
bash statement os2 Programming 2 03-20-2005 10:13 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 05:08 PM.

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