3

Consider there is a variable line and variable word:

line = 1234 abc xyz 5678
word = 1234

The value of these variables are read from 2 different files.

I want to print the line if it contains the word. How do I do this using shell script? I tried all the suggested solutions given in previous questions. For example, the following code always passed even if the word was not in the line.

if [ "$line"==*"$word"*]; then
    echo $line
fi
eddyrokr
  • 414
  • 1
  • 8
  • 23
  • possible duplicate of [String contains in bash](http://stackoverflow.com/questions/229551/string-contains-in-bash) – Kevin Aug 21 '13 at 13:09
  • You might want to check out this old question that is one of the highest voted on stackoverflow. http://stackoverflow.com/questions/229551/string-contains-in-bash – gNU.be Aug 21 '13 at 07:39
  • @Kevin: I already tried those answers and did not get the expected result. I have explained this in the question too. – eddyrokr Aug 21 '13 at 17:14

8 Answers8

4

No need for an if statement; just use grep:

echo $line | grep "\b$word\b"
4

You can use if [[ "$line" == *"$word"* ]]

Also you need to use the following to assign variables

line="1234 abc xyz 5678"
word="1234"

Working example -- http://ideone.com/drLidd

Bill
  • 5,263
  • 6
  • 35
  • 50
4

Watch the white spaces!

When you set a variable to a value, don't put white spaces around the equal sign. Also use quotes when your value has spaced in it:

line="1234 abc xyz 5678"   # Must have quotation marks
word=1234                  # Quotation marks are optional

When you use comparisons, you must leave white space around the brackets and the comparison sign:

if [[ $line == *$word* ]]; then
    echo $line
fi

Note that double square brackets. If you are doing pattern matching, you must use the double square brackets and not the single square brackets. The double square brackets mean you're doing a pattern match operation when you use == or =. If you use single square brackets:

if [ "$line" = *"$word"* ]

You're doing equality. Note that double square brackets don't need quotation marks while single brackets it is required in most situations.

Community
  • 1
  • 1
David W.
  • 105,218
  • 39
  • 216
  • 337
  • Thanks - these tips are quite helpful – Baiyan Huang Aug 21 '13 at 01:09
  • question: why "single brackets it is required in most situations."? – Baiyan Huang Aug 21 '13 at 01:12
  • Ok, got it: [ $a == z* ] # File globbing and word splitting take place. – Baiyan Huang Aug 21 '13 at 01:41
  • 1
    The double brackets are a special _internal_ test and are not interpolated by the shell first. The single brackets, although they are now a builtin command, stem from the old `/bin/test` and `/bin/[` commands. The statement is fully interpolated by the shell first, and then the test is done. Thus, if `line="This is a test"`, you couldn't do `[ $line = "foo" ]` because the shell will replace `$line` and then think there are too many parameters for the test command. However, `[[ $line = "foo" ]]` is fine. – David W. Aug 21 '13 at 05:32
  • @DavidW.: Thanks for the detailed explanation on the use of brackets. It worked when I used bash. But why does this does not work with sh? – eddyrokr Aug 21 '13 at 17:45
  • @eddyrokr Look at this http://stackoverflow.com/questions/16551033/difference-between-sh-and-bash-when-symlink-is-used – Bill Aug 21 '13 at 23:22
  • @eddyrokr BASH shell emulates the POSIX shell when called as `sh` vs. `bash`. The Posix shell has fewer features and the `[[..]]` is one of them. This was introduced with the Kornshell, and BASH took many of the Kornshell innovations. – David W. Aug 21 '13 at 23:57
3
echo $line | grep "$word"

would be the typical way to do this in a script, of course it does cost a new process

tolanj
  • 3,651
  • 16
  • 30
  • I get some messages: Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more information. I get this even after using the '-s' option while using grep. – eddyrokr Aug 21 '13 at 00:43
  • Could be that `$word` starts with a hyphen, so it is safer to use `grep -- "$word"` – cdarke Aug 21 '13 at 07:47
3

You can use the bash match operator =~:

 [[ "$line" =~ "$word" ]] && echo "$line"

Don't forget quotes, as stated in previous answers (especially the one of @Bill).

Bentoy13
  • 4,886
  • 1
  • 20
  • 33
1

The reason that if [ "$line"==*"$word"* ] does not work as you expect is perhaps a bit obscure. Assuming that no files exist that cause the glob to expand, then you are merely testing that the string 1234 abc xyz 5678==*1234* is non empty. Clearly, that is not an empty string, so the condition is always true. You need to put whitespace around your == operator, but that will not work because you are now testing if the string 1234 abc xyz 5678 is the same as the string to which the glob *1234* expands, so it will be true only if a file named 1234 abc xyz 5678 exists in the current working directory of the process executing the shell script. There are shell extensions that allow this sort of comparison, but grep works well, or you can use a case statement:

case "$line" in
*$word*) echo $line;;
esac
William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

An alternative solution would be using loop:

for w in $line
do
    if [ "$w" == "$word" ]; then
        echo $line
        break
    fi
done
Baiyan Huang
  • 6,463
  • 8
  • 45
  • 72
0

Code Snippet:

$a='text'
$b='text'

if [ $a -eq $b ]
 then
   msg='equal'
fi 
Nagama Inamdar
  • 2,851
  • 22
  • 39
  • 48
NS23
  • 684
  • 5
  • 14