Why can’t I grep this way

grepsed

I would like to change the line "disable = yes" to "disable = no" into the following file :

[root@centos2 ~]# cat /etc/xinetd.d/tftp
service tftp
{
    ...
    server_args             = -s /var/lib/tftpboot
    disable                 = yes
    per_source              = 11
    ...
}  

I tried this :

[root@centos2 ~]# grep 'disable                 = yes' /etc/xinetd.d/tftp
[root@centos2 ~]#

by just copying the space with my mouse but it doesn't grep anything…

Why and how can I know what are the elements between "disable" and "=" ? Is it several spaces? tabulations?

I know I can grep using the following regex :

[root@centos2 xinetd.d]# grep -E 'disable.+= yes' /etc/xinetd.d/tftp
    disable                 = yes
[root@centos2 xinetd.d]#

And finaly, is there a better way of replacing "yes" by "no" using sed than the following :

[root@centos2 xinetd.d]# sed -r 's/disable.+= yes/disable                 = 
no/g' /etc/xinetd.d/tftp

service tftp
{
    ...
    server_args             = -s /var/lib/tftpboot
    disable                 = no
    per_source              = 11
    ...
}

EDIT :

Result of the od command thanks @ilkkachu

[root@centos2 xinetd.d]# < /etc/xinetd.d/tftp grep disable | od -c
0000000  \t   d   i   s   a   b   l   e
0000020                                       =       y   e   s  \n
0000037

Best Answer

The spaces are more commonly known as "whitespace", and can include not just spaces but tabs (and other "blank" characters). In a regular expression you can often refer to these either with [[:space:]] or \s (depending on the RE engine) which includes both horizontal (space, tab and some unicode spacing characters of various width if available) for which you can also use [[:blank:]] and sometimes \h and vertical spacing characters (like line feed, form feed, vertical tab or carriage return). [[:space:]] is sometimes used in place of [[:blank:]] for its covering of the spurious carriage return character in Microsoft text files.

You cannot replace with grep - it's just a searching tool. Instead, to replace the yes with no you can use a command like this:

sed '/disable\>/s/\<yes\>/no/' /etc/xinetd.d/tftp

This tells sed to substitute (change) the word yes into no on any line that contains the word disable. (The \> (initially a ex/vi regexp operator), in some sed implementations, forces an end-of-word (though beware it's not whitespace-delimited-words, it would also match on disable-option)). Conveniently this sidesteps the issue of whitespace altogether.


Be careful: with a line such as eyes yes, an unbounded yes substitution would apply to the first instance of yes and leave you with eno yes. That's why I have used \<yes\> instead of just yes.

Related Question