3

For example, I have a string like this: 1341 5415 fdad.

Command grep -E "(^|\s)[1-9]{1,5}($|\s)" -o will give only 1341, but I want to get 1341 and 5415.

How can I do this?

3 Answers 3

6
echo '1341 5415 fdad' | grep -E -o '\b[1-9]{1,5}\b'

Output:

1341
5415

-E: Interpret PATTERNS as extended regular expression

-o: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

\b: zero-width word boundary

4

The actual match you get is 1341␣, with the trailing space. And grep doesn't look for overlapping matches, so when that space is taken by the first match, the pattern doesn't match again on the rest of the line. But if the input was 123 456 789, the two strings 123␣ and ␣789 would be matched.

It's probably easier to use grep -w:

-w, --word-regexp
Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent character.

$ echo '1341 5415 fdad' |  grep -wE "[1-9]{1,5}" -o
1341
5415

Alternatively, you could double all spaces before the grep:

$ echo '1341 5415 fdad' | sed -e 's/ /  /g' | grep -E "(^|\s)[1-9]{1,5}($|\s)" -o
1341 
 5415 

(or with sed -e 's/\s/ /g' if that works in your sed.)

There's a trailing space in 1341 line, and a leading one in the 5415, those are part of the matches.

4
  • Very clever. Now we will never know whether I would have discovered on my own... Nov 25, 2021 at 21:06
  • But now for input "1341+1234" I will get 1341 and 1234 instead of empty output
    – telec2014
    Nov 25, 2021 at 21:47
  • 3
    @ВиталийЕгоров, if separators other than space were part of your issue, you could have said so in the question...
    – ilkkachu
    Nov 25, 2021 at 22:00
  • @ilkkachu, thank you very much, you've helped me a lot
    – telec2014
    Nov 25, 2021 at 22:06
3

One method is to change all spaces to a newline, then use grep -x to select lines that exactly match your expression:

$ echo '1341 5415 fdad' | tr -s '[:space:]' '[\n*]' | grep -xE -e '[1-9]{1,5}'
1341
5415
1
  • should work with just tr -s '[:space:]' '\n' since tr is supposed to extend the second list of characters by repeating the last one as necessary to match the length of the first
    – ilkkachu
    Nov 26, 2021 at 9:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .