Results 1 to 9 of 9

Thread: Bash, string comparison

  1. #1
    Join Date
    Jan 2010
    Location
    No longer SoFl
    Beans
    Hidden!
    Distro
    Ubuntu Mate 16.04 Xenial Xerus

    Bash, string comparison

    My end goal is to read some weather information from a text or xml file, extract the temperature and write it on an image file using convert. I am trying to take it one step at a time learn a little and improve on my bash scrip. Convert works fine calling it from a script and creating an image with a variable's text on it.

    Now I want to read from a text file and this is where I am running into problems. Every tutorial on the Internet gives similar examples that fail. My text file is simple
    sample.txt contains:
    Code:
    Line one
    Line 2
    Line Three
    Line four
    Line 5
    Line SIX
    Code:
    #!/bin/bash
    while read LINE
    do 
    if [ $LINE = *four* ]
    then
        echo "contains four"
    fi
    done < "sample.txt"
    Produces "[: 11: Line: unexpected operator" five times, if I use the ";" after the [ or not.
    Using double brackets produces "readit.sh: 8: [[: not found" repeat five times if I use the ";" after the bracket or not.

    I have tried several different versions of string comparison all which fail, even when I copy the exact example from a website.

    What is the proper way to compare a sting in bash? (or to extract a specific line from a text file)


    I am using 10.4.3 and have bash version 4.1.5(1)-release (x86_64-pc-linux-gnu)



  2. #2
    Join Date
    Nov 2008
    Location
    Boston MetroWest
    Beans
    16,326

    Re: Bash, string comparison

    if [ $LINE = *four* ]
    I'd use

    Code:
    if [ "$(echo $LINE | grep 'four')" != "" ]
    The expression "echo $LINE | grep 'four'" will match any line with the text "four" in it. If you want to be more stringent, you can use a more complex regular expression. For instance "grep 'four$'" would only match the text "four" it if came at the end of the line.

    The $() operator returns the results of the command. In this case it will return the entire contents of any line containing the string 'four'. That result is tested against the empty string using the not-equal operator. So a line with the text "four" will make the LHS of the comparison not empty, and thus the entire logical expression will be true.

  3. #3
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Bash, string comparison

    double brackets work just fine here
    Code:
    while read LINE
    do 
      echo $LINE $( if [[ $LINE = *four* ]]; then echo "contains four";  fi )
    done < "sample.txt"
    output:
    Code:
    $ ./if.sh 
    Line one
    Line 2
    Line Three
    Line four contains four
    Line 5
    Line SIX
    single brackets will fail because they don't prevent word splitting (words in $LINE get delimited at whitespaces and will appear as separate arguments) while [[ does.

    also consider not using all-caps for variable names, you risk overwriting some environment variable by accident (envvars are all-caps by convention)
    Last edited by Vaphell; January 29th, 2012 at 09:33 AM.

  4. #4
    Join Date
    Jan 2010
    Location
    No longer SoFl
    Beans
    Hidden!
    Distro
    Ubuntu Mate 16.04 Xenial Xerus

    Re: Bash, string comparison

    I found the reason for my problem. I have been calling my programs with "sh (program_name).sh" which produces the errors. I saw Vaphell's example and used ./(program_name).sh and it worked fine.

    I have no idea when I started using "sh (program_name).sh" but I saw it used somewhere and continued with it. For some reason it works with some scripts and obviously not others.
    "bash (program_name).sh " also works fine. I am going to work on this some more and if it works I will mark the thread solved.
    Last edited by SoFl W; January 30th, 2012 at 04:03 AM. Reason: It is the way I am calling the code.



  5. #5
    Join Date
    Jan 2008
    Location
    Manchester UK
    Beans
    13,573
    Distro
    Ubuntu

    Re: Bash, string comparison

    You sure you didn't make a typo

    Code:
    nothingspecial@magik:~$ while read LINE
    > do 
    >   echo $LINE $( if [[ $LINE = *four* ]]; then echo "contains four";  fi )
    > done < "sample.txt"
    Line one
    Line 2
    Line Three
    Line four contains four
    Line 5
    Line SIX

  6. #6
    Join Date
    Jan 2010
    Location
    No longer SoFl
    Beans
    Hidden!
    Distro
    Ubuntu Mate 16.04 Xenial Xerus

    Re: Bash, string comparison

    Thank you everyone for your help. The code worked but the way I called the code didn't. That was frustrating to copy examples and the examples not working. My script is slowly coming around and working close enough to the way I would like. Again thank you for your help, it helped me see my error.
    From what I can see calling 'sh' but using "#!/bin/bash' in my script didn't make the interpretor happy. I am reading up on the differences between bash and sh but I still don't quite see the major differences or advantages of one over the other.

    Thanks




  7. #7
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Bash, string comparison

    sh is symlink to dash.
    hashbang line would invoke bash, but you have overriden it by calling sh explicitly. Bash has more features but is considered fat by some. It's perfect for user sessions where all kinds of stuff happen but there are uses for leaner flavors of shell so system can run scripts without the bloat when possible.
    Last edited by Vaphell; January 30th, 2012 at 01:55 AM.

  8. #8
    Join Date
    Feb 2007
    Location
    Romania
    Beans
    Hidden!

    Re: Bash, string comparison

    Quote Originally Posted by SeijiSensei View Post
    I'd use

    Code:
    if [ "$(echo $LINE | grep 'four')" != "" ]
    The expression "echo $LINE | grep 'four'" will match any line with the text "four" in it. If you want to be more stringent, you can use a more complex regular expression. For instance "grep 'four$'" would only match the text "four" it if came at the end of the line.

    The $() operator returns the results of the command. In this case it will return the entire contents of any line containing the string 'four'. That result is tested against the empty string using the not-equal operator. So a line with the text "four" will make the LHS of the comparison not empty, and thus the entire logical expression will be true.
    There is no need for the test (`[') command. The syntax of the if statement is:
    Code:
    if COMMANDS; then
        COMMANDS
    fi
    POSIX:
    Code:
    while read -r line; do
        if printf '%s' "$line" | grep "REGEX" > /dev/null 2>&1; then
            printf '%s\n' "whatever"
        fi
    done < file
    In BASH, instead of echo or printf you can use a here string:
    Code:
    if grep "REGEX" <<< "$LINE"; then ...
    But, as suggested by Vaphell, in BASH, you can use the compound test command `[[':
    Code:
    if [[ $line =~ "ERE" ]]; then ...
    where ERE is an extended regular expression.

    See:
    http://mywiki.wooledge.org/BashGuide..._and_.5B.5B.29
    and BashFAQ 031.

  9. #9
    Join Date
    Jan 2010
    Location
    No longer SoFl
    Beans
    Hidden!
    Distro
    Ubuntu Mate 16.04 Xenial Xerus

    Re: Bash, string comparison

    Thank you for this additional information. Once I started calling the script correctly it started working. I was able to write the code and get it working. It may not be perfect, I am sure it could be improved but I was able to get done what I wanted to get done and improve my knowledge. As I continue to improve my knowledge I will write more efficient code. For now the script works the way I want.



Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •