7

I'm trying to write a grep command to find lines like the below in a large text file:

<div class="node_thumbnail" data-type="file" name="GOPR0036.MP4_frame000001.jpg" data="813334c25191468c9f1c57afc99fde60" aid="133948" rel="/Files/ToolTipView?fileId=813334c25191468c9f1c57afc99fde60&pageNo=1&NoCache=101016083044" rev="topMiddle">

but the + symbol seems to be causing problems in the below commands:

 grep 'data=[a-z,0-9,\"]' file

Lots of hits

 grep 'data=[a-z,0-9,\"]+' file

No hits

  • 1
    A large HTML file, to be more specific ... not that there's anything wrong with that ... – Reinier Post Oct 11 '16 at 10:35
  • just don't forget to take the habit of having: LC_ALL="C" grep ... instead of grep ... , so that [a-z] means always ascii letters a to z (ie, all lowercase ascii letters) instead of funny alternatives (ex: every letters except "Z", in some locales...) – Olivier Dulac Oct 11 '16 at 11:28
  • and [a-z,0-9,\"] contains 2 occurence of ",", which is not necessary. you can have the same effect with [a-z,0-9\"] – Olivier Dulac Oct 11 '16 at 11:30
14

If you want + to mean "one or more of the preceding atom", then you have to do one of:

  1. Use -E (Extended Regular Expressions) (or -P, PCRE):

    grep -E 'data=[a-z,0-9,\"]+' file
    
  2. Escape + so that is treated specially in the Basic Regular Expressions used by default in grep:

    grep 'data=[a-z,0-9,"]\+' file
    
| improve this answer | |
  • @MartinKS by the way, if all you want is the quoted string after data=, you could just run grep -P 'data=".+?" or, to get only the string and nothing else: grep -oP '\bdata="\K[^"]+'. – terdon Oct 10 '16 at 12:52
  • 2
    @MartinKS whoops, to get only the string, you need the -o option as well. I edited my previous comment. And you're welcome :) – terdon Oct 10 '16 at 12:58
  • @terdon, or just sed -n 's/.*data="\([^"][^"]*\)".*/\1/p' file, which is fully POSIX compliant. (And sed -nE 's/.*data="([^"]+)".*/\1/p' file will be POSIX compliant for the next edition of POSIX.) – Wildcard Oct 11 '16 at 10:42
9

Points:

  • + is an ERE (Extended Regular Expression) token, which indicates one or more of the preceding token, can be used if -E option of grep is used or with escaped (\+) in case of BRE (Basic Regex) i.e. only regular grep

  • The character class [a-z,0-9,\"] would match any of the characters between [a-z], [0-9], , or ". This may not be what you want

  • Normally grep outputs whole line, if you want to output only the matched portion, use -o option of grep


Based on your example, you can do:

grep -E '\bdata=[a-z0-9"]+\b' file
  • -E enables ERE
  • \b matches string edges, zero width
  • data= matches data= literally
  • [a-z0-9"] matches any character of [a-z], [0-9], and ". + matches the previous token one or more times

Your current pattern even you make it correct, without \b this would match false positives like foo fdata=2322ab, data=12AB and so on.

Example:

% grep -oE '\bdata=[a-z0-9"]+\b' <<<'<div class="node_thumbnail" data-type="file" name="GOPR0036.MP4_frame000001.jpg" data="813334c25191468c9f1c57afc99fde60" aid="133948" rel="/Files/ToolTipView?fileId=813334c25191468c9f1c57afc99fde60&pageNo=1&NoCache=101016083044" rev="topMiddle"'
data="813334c25191468c9f1c57afc99fde60
| improve this answer | |
-1

Another option is to use egrep:

egrep 'data=[a-z,0-9,\"]+' file

egrep is bundled with grep, it is just a wrapper for grep:

#!/bin/sh
exec grep -E "$@"

this is good for interactive use. However in scripts I would use grep -E.

| improve this answer | |
  • Please don't recommend using egrep. It has been deprecated in favor of grep -E for many years now. As the POSIX specs state, it is still supported and likely to be so for a while but the current POSIX (and GNU) grep has been designed to replace the older egrep and fgrep variants so it is better to use grep -E and grep -f instead. – terdon Oct 11 '16 at 11:49
  • egrep is fine for interactive use – Steven Penny Oct 11 '16 at 12:09

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.