Q:

Linux bash: grep with regex error

I am trying to detect a NIC is configured or not. (On Ubuntu 1604, so the main configuration file will be /etc/network/interfaces).
I prepared a regex to search the configure from the interfaces file like below:
^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+eth0

This regex works when I put it in grep command directly; but if I put this regex into a variable then used it in grep, then grep will throw error:
grep: Invalid regular expression

Can you please help to figure out why put that it does not work that put regex into a variable?  
Thanks!
root@ci-1-0:/home/lisa# mainfn=/etc/network/interfaces
root@ci-1-0:/home/lisa# nic_name=eth0
root@ci-1-0:/home/lisa# pattern="^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+$nic_name"
root@ci-1-0:/home/lisa# echo $pattern
^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+eth0

root@ci-1-0:/home/lisa# grep -E "^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+eth0" $mainfn
auto eth0
iface eth0 inet dhcp

root@ci-1-0:/home/lisa# grep -E $pattern $mainfn
grep: Invalid regular expression

A:

On my OS Sierra terminal, your example gives a slightly different error message:
> grep -E $pattern filename
grep: brackets ([ ]) not balanced

But if I wrap the pattern in quotes, it works fine:
> grep -E "$pattern" filename
auto eth0
iface eth0 inet dhcp

The issue is that without quotes, the space in your pattern is being interpreted as a separator between arguments:
grep -E ^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+eth0 filename
          ^ HERE                             ^ (and also here)

In other words, it is trying to search for an invalid regex ^[ (with unbalanced brackets, hence my error message), in three files: "\t]*(auto|iface|mapping|allow-.*)[", "\t]+eth0" (which obviously do not exist), and "filename".

As a general rule in bash, it's a good idea to wrap any use of variables in quotes like this, to avoid such whitespace issues.

