69

Example:

file="123 hello"

How can I edit the string file such that it only contains the numbers and the text part is removed?

So,

echo $file

should print 123 only.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Ayush Mishra
  • 1,583
  • 3
  • 13
  • 13

2 Answers2

121

This is one way with sed:

$ echo $file | sed 's/[^0-9]*//g' 
123
$ echo "123 he23llo" | sed 's/[^0-9]*//g'
12323

Or with pure bash:

$ echo "${file//[!0-9]/}" 
123
$ file="123 hello 12345 aaa"
$ echo "${file//[!0-9]/}" 
12312345

To save the result into the variable itself, do

$ file=$(echo $file | sed 's/[^0-9]*//g')
$ echo $file
123

$ file=${file//[!0-9]/}
$ echo $file
123
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 3
    In the interest of completeness, you can also save the result back in the same variable with the pure bash form: `file=${file//[!0-9]/}`. Also, you can in general replace `echo ` *something* `|` *command* with *command* `<<<` *something*. – Mark Reed Nov 01 '13 at 20:32
  • Good point, @MarkReed. As per the kind of user asking I preferred to leave the answer very naive, as `<<<` can be strange for people starting to bash-script. I update my answer with the `file=$file{file//[!0-9]/}`, many thanks! – fedorqui Nov 02 '13 at 15:19
  • Looking to do this for a version string (e.g. `git version 1.7.1`)? Use `${gitVersion//[!0-9.]/}` and it keeps the periods. – bbodenmiller Mar 15 '17 at 07:08
  • Out of curiosity, why does this command not delete whitespace in the string? This is actually the behavior I wanted, but don't understand why it's the default. – Luke Davis Mar 07 '18 at 09:21
  • @LukeDavis not sure what you tried, but I tested and it does work: `file="hola que tal 23"` and then `echo "${file//[!0-9]/}"` returns 23. – fedorqui Mar 07 '18 at 09:52
  • Sorry should have been more specific (and I was mistaken). `echo hello 1 2 3 | sed 's/[^0-9]*//'` (not your example) returns `1 2 3`, but your example, `echo hello 1 2 3 | sed 's/[^0-9]*//g'`, returns `123`. Wondering why leaving out the `g` preserves spaces. – Luke Davis Mar 07 '18 at 10:12
  • @LukeDavis `/g` stands for "global replacement". When used, any replacement is done as many times as possible within the line. Otherwise, as you just saw, it just happens once. Compare `sed 's/./X/' <<< "hello"` with `sed 's/./X/g' <<< "hello"` (spoiler: they return "Xello" and "XXXXX"). – fedorqui Mar 07 '18 at 10:19
9

You can say:

echo ${file%%[^0-9]*}

However, this runs into problems in certain cases:

$ file="123 file 456"
$ echo ${file%%[^0-9]*}
123

Using tr:

$ file="123 hello 456"
$ new=$(tr -dc '0-9' <<< $file)
$ echo $new
123456
devnull
  • 118,548
  • 33
  • 236
  • 227
  • 1
    "certain cases"? `${file%%[^0-9]*}` will always remove everything from the first non-digit to the end of the string. `%%` is not what you want here at all (nor is `%` or `#` or `##`). I feel like I'm missing a joke here. – Mark Reed Nov 01 '13 at 10:12
  • Dear @MarkReed, I thought that what you're saying was made clear in the answer itself, or not? Probably that was the reason that another approach was suggested. Am I missing something here? – devnull Nov 01 '13 at 10:15
  • @MarkReed Moreover, feel free to add your answer. I'll be glad to delete this. – devnull Nov 01 '13 at 10:16
  • 3
    @devnull I'm just failing to understand the goal of bringing up an obviously incorrect solution before turning around and offering a correct one, and then commenting on your own answer asserting that there's something terribly wrong with it. Perhaps it's a pedagogical technique instead of a joke, but either way I fear it went over my head completely. – Mark Reed Nov 01 '13 at 10:43
  • 5
    @devnull, I wish I could downvote comments. There's no place for personal attacks here. – glenn jackman Nov 01 '13 at 13:48
  • 3
    I give +1 to this answer. The first solution may be useful in some simple cases like the example which was provided by the OP. So, I don't see any problems to propose this solution although I would have tendency to always use `sed`. Moreover, devnull has warned about the limitations of this first solution and gave another one that works well. More solutions, more wealth. – Idriss Neumann Nov 01 '13 at 14:34