Ankur Agarwal
Ankur Agarwal

Reputation: 24778

Use grep to match a pattern in a line only once

I have this:

echo 12345 | grep -o '[[:digit:]]\{1,4\}'

Which gives this:

1234
5

I understand whats happening. How do I stop grep from trying to continue matching after 1 successful match?

How do I get only

1234

Upvotes: 10

Views: 32748

Answers (5)

prem
prem

Reputation: 1

grep manpage says on this topic (see chapter 'regular expressions'):

 (…)

 {n,}

      The preceding item is matched n or more times. 

 {n,m}     
  
      The preceding item is matched at least n times, but not more than m times. 

 (…)

So the answer should be:

echo 12345 | grep -o '[[:digit:]]\{4\}'

I just tested it on cygwin terminal (2018) and it worked!

Upvotes: 0

koyae
koyae

Reputation: 770

If – as in your example – your numeric expression will appear at the beginning of the string you're starting with, you could just add a start-of-line anchor ^:

echo 12345 | grep -o '^\([[:digit:]]\)\{1,4\}'

Depending on which exact digits you want, an end-of-line anchor $ might help also.

Upvotes: 0

MacUsers
MacUsers

Reputation: 2231

You need to do the grouping: \(...\) followed by the exact number of occurrence: \{<n>\} to do the job:

maci:~ san$ echo 12345 | grep -o '\([[:digit:]]\)\{4\}'
1234

Hope it helps. Cheers!!

Upvotes: 6

Jonathan Leffler
Jonathan Leffler

Reputation: 755016

Use sed instead of grep:

echo 12345 | sed -n '/^\([0-9]\{1,4\}\).*/s//\1/p'

This matches up to 4 digits at the beginning of the line, followed by anything, keeps just the digits, and prints them. The -n prevents lines from being printed otherwise. If the digit string might also appear mid-line, then you need a slightly more complex command.

In fact, ideally you'll use a sed with PCRE regular expressions since you really need a non-greedy match. However, up to a reasonable approximation, you can use: (A semi-solution to a considerably more complex problem...now removed!)

Since you want the first string of up to 4 digits on the line, simply use sed to remove any non-digits and then print the digit string:

echo abc12345 | sed -n '/^[^0-9]*\([0-9]\{1,4\}\).*/s//\1/p'

This matches a string of non-digits followed by 1-4 digits followed by anything, keeps just the digits, and prints them.

Upvotes: 3

Andrew White
Andrew White

Reputation: 53516

Do you want grep to stop matching or do you only care about the first match. You could use head if the later is true...

`grep stuff | head -n 1` 

Grep is a line based util so the -m 1 flag tells grep to stop after it matches the first line which when combined with head is pretty good in practice.

Upvotes: 10

Related Questions