Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

So, I have 50+ words and I have to match the numbers in them. These numbers can be 3 or 4 digit numbers. I think I tried every way there is, but nothing seems to work (I need to remember the number as a pattern). My attempts:

'/\(.*\)\([0-9][0-9]?[0-9][0-9]\)\(.*\)/'
'/\(.*\)\([0-9]\{3,4\}\)\(.*\)/'
'/\(.*\)\(([0-9][0-9][0-9][0-9]|[0-9][0-9][0-9])\)\(.*\)/'
...

It always matches only 3 numbers, or the whole word.

INPUT:

1844-PAL.Bak 
IMG_1959.bak  
ZER_1940.BAK  
PEN225.bak
word-1943.BAK

NEED TO REMEMBER AS A PATTERN:

1844
1959
1940
225
1943
share|improve this question
2  
Could you show us an example of your input? –  terdon May 19 at 14:35
    
edited the question. –  Wanderer May 19 at 14:39
    
Thanks, but is that an example of one of your input lines? Please show us a few lines of your file and your desired output. Can all 4 examples be on the same line or does each line only have one of these forms? –  terdon May 19 at 14:40
    
oh, okay, sorry. didn't think it would matter. give me a minute. :) –  Wanderer May 19 at 14:41

2 Answers 2

up vote 3 down vote accepted

There are many ways to do this. The following commands assume that each input line can only have one number. I am using this file as a test:

1844-PAL.Bak 
IMG_1959.bak  
ZER_1940.BAK  
PEN225.bak
word-1943.BAK
  1. sed

    $ sed -r 's/([^0-9]*)([0-9]*)([^0-9]*)/1:"\1", 2:"\2", 3:"\3"/' file
    1:"", 2:"1844", 3:"-PAL.Bak "
    1:"IMG_", 2:"1959", 3:"bak  "
    1:"ZER_", 2:"1940", 3:"BAK  "
    1:"PEN", 2:"225", 3:"bak"
    1:"word-", 2:"1943", 3:"BAK"
    
  2. perl

    $ perl -lpe 's/([^\d]*)(\d*)([^\d])/1:"$1", 2:"$2", 3:"$3"/' file
    1:"", 2:"1844", 3:"-"PAL.Bak 
    1:"IMG_", 2:"1959", 3:"."bak  
    1:"ZER_", 2:"1940", 3:"."BAK  
    1:"PEN", 2:"225", 3:"."bak
    1:"word-", 2:"1943", 3:"."BAK
    
  3. grep

    $ grep -oP '\d+' file
    1844
    1959
    1940
    225
    1943
    

If you only have one pattern of interest per line, you can simplify to

 $ sed -r 's/[^0-9]*([0-9]*).*/Matched: \1/' file
Matched: 1844
Matched: 1959
Matched: 1940
Matched: 225
Matched: 1943

or

$ perl -lpe 's/.*?(\d+).*/Matched $1/' file
Matched 1844
Matched 1959
Matched 1940
Matched 225
Matched 1943

In general, with regular expressions, less is more. You should always try and use the simplest regular expression necessary. If you don't want to capture or match the non-number characters, then leave them out of the regex.

share|improve this answer
    
Thank you for your answer. Only thing though - in the sed version (the first one there) it does leave a dot there in "\2". Any chance we can get rid of that? –  Wanderer May 19 at 15:03
    
@Wanderer yes, sorry, I did that before you added your input since I assumed that you would also want to match decimal numbers. See updated answer. Also, I suggest you use the simpler sed one at the end, no need for the complexity of the first versions for what you are attempting. –  terdon May 19 at 15:05
    
Perfect, detailed answer. Thank you. –  Wanderer May 19 at 15:08

Try the below GNU grep command,

grep -oP '[0-9]{3,4}' file
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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