Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I use a variable string in a regular expressions

 while read line
    do
        if [[ line =~ *"$key"* ]]; then
            echo line
        fi
    done < "$filename"

$key is a string variable and I want to print all the lines that has the value of $key

share|improve this question
    
Are you sure about that pattern? *$key* would be quite the odd pattern to match if $key were something like ^foo or foo$, resulting in a pattern of *^foo* or *foo$*. –  DopeGhoti Jan 3 at 18:17
1  
@DopeGhoti The question is about why the script doesn't work, and those errors you fixed in your edit are why it doesn't. Editing the question to fix the errors actually renders the question useless... –  derobert Jan 3 at 18:23
    
My apologies for the faux-pas. –  DopeGhoti Jan 3 at 18:24
    
@DopeGhoti No problem. Edits to fix errors like that are generally welcome in answers. You probably want to be wary of editing code in questions, as the error might be the cause of the problem. Of course, feel free to fix grammar, spelling, formatting, etc. –  derobert Jan 3 at 18:28
1  
Duly noted, @derobert; thanks kindly. –  DopeGhoti Jan 3 at 18:29

2 Answers 2

up vote 7 down vote accepted

You've made a few mistakes there. Here's your script corrected:

while read line
do
    if [[ "$line" =~ "$key" ]]; then
        echo $line
    fi
done < "$filename"

Though it seems it could be replaced with a simple grep:

grep "$key" "$filename"
share|improve this answer
    
grep "$key" "$filename" is not exactly equivalent, since in this context, $key is interpreted as a BRE. Use -F to avoid this. –  Chris Down Jan 3 at 18:14
    
the grep works fine but the while loop isn't doing anything, thanks though! –  user2798694 Jan 3 at 18:23
1  
@user2798694: that's what Janos meant ^^ : no longer use the "while ..... done", but instead just use: grep "$key" "$filename" . grep will only output lines matching $key in the file $filename, which seems to be what you were trying to do? [unless you wanted to do additionnal things for each matched lines?] –  Olivier Dulac Jan 3 at 18:27
    
Better correct the regular expression syntax: [[ "$line" =~ .*"$key".* ]]. –  manatwork Jan 3 at 18:35
2  
@manatwork, janos, how is that different from [[ "$line" =~ "$key" ]]? AFAIK, =~ already means "true if matches", not ==. –  terdon Jan 3 at 19:23

First, whenever you're using the value of a variable, you need to write $line.

Also, note that read line strips off leading and trailing whitespace, and allows the sequence backslash-newline as a line continuation. To retain whitespace, use IFS= read. To avoid treating \ specially, use read -r. You can of course combine the two as IFS= read -r.

What do you want to test exactly? If you want to test that the line is exactly $key (except for whitespace unless you use IFS= read), use the == operator, and make sure to put $key in double quotes.

if [[ $line == "$key" ]]; then …

If you want to test that the line contains $key (so for example if the value of key is fu*bar then hellofu*bar and fu*barqux match, but fuubar and gu*bar don't), then use the == operator and again make sure to put $key in double quotes. The right-hand side of the == operator is a shell wildcard pattern; putting the variable in double quotes causes it to be treated literally.

if [[ $line == *"$key"* ]]; then …

If you want to treat $key as a wildcard pattern, so that if $key is fu*bar then the line can be fubar or fuqwebar but not fbar or afubar, then leave off the double quotes:

if [[ $line == $key ]]; then …

If you only want part of the line to match, allowing things like afubar:

if [[ $line == *$key* ]]; then …

Use the regular expression match operator =~ if you want to have an extended regular expression on the right-hand side. A regular expression can match part of the line; if you want to match the whole line, put ^ at the beginning of the regex and $ at the end. For example, [[ $line == *"$key"* ]] is equivalent to [[ $line =~ "$key" ]] while [[ $line == "$key" ]] is equivalent to [[ $line =~ ^"$key"$ ]].

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.