2

How can I grep for a combination of tab and star (*) characters in a text file?

For example:

Input:

text    *    0    *    0    *    *    some_text
text    *    9    45   9    0    0    some_text
TEXT    *    0    *    0    0    *    some_text

I need to grep for a specific combination of tab and star and zeros, say for example:

*    0    *    0    0    *

Expected output:

TEXT    *    0    *    0    0    *    some_text

I can grep for stars, separately, using:

grep -P '\t' input > output

I can grep for tabs, separately, using:

grep '\*' input > output

But how can I combine both? I'm trying, unsuccessfully, the following combination:

grep -P '\*\t0\t\*0\t0\*' input > output
  • 2
    You're missing a couple of tabs in '\*\t0\t\*0\t0\*': in the middle there's a *0, and in the end a 0*. grep -P '\*\t0\t\*\t0\t0' might work. – ilkkachu Aug 4 '16 at 12:43
  • oh this was incredibly noobish – dovah Aug 4 '16 at 12:50
  • 1
    Though it might be helpful to build a pattern like that from an array or something, a Perl solution that comes in mind would be perl -ne '$pat = join "\t", qw/* 0 * 0 0 */; print if /\Q$pat/' – ilkkachu Aug 4 '16 at 12:52
4

Portably:

tab=$(printf '\t')
grep -F "*${tab}0${tab}*${tab}0${tab}0"

With some shells (ksh93, zsh, bash, mksh, FreeBSD sh), you can use:

grep -F $'*\t0\t*\t0\t0'

($'\t' can also be written $'\u0009' or (on ASCII-based systems) $'\x09', $'\11' or $'\CI')

Some grep implementations like ast-open's one recognise \t (or \x09) themselves as meaning a tab character. So you can do:

grep '\*\t0\t\*\t0\t0'

(same with other regexp types there (-E for ERE, -P for perl-like (similar to PCRE), -A for augmented).

GNU grep (at least on GNU systems) doesn't recognise \t nor \x09 with BRE or ERE, but does with PCREs (when the support has been built-in), (and also \x09 or \11).

grep -P '\*\t0\t\*\t0\t0'

would work with GNU grep as long as PCRE support has been enabled (which tends to be the case on modern systems).

Another portable solution is to use awk instead were the \t is universally supported:

awk '/\*\t0\t\*\t0\t0/'
1

According to ilkkachu comment:

Because there are missing a couple of tabs in '*\t0\t*0\t0*': in the middle there's a 0, and in the end a 0.

The command:

grep -P '\*\t0\t\*\t0\t0'

will solve that issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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