Reputation: 2510
Sorry, I'll explain it better
How can I get the last number from string?
Examples of generics strings:
If str=str1s2
echo $str | cmd?
I get 2
If str=234ef85
echo $str | cmd?
I get 85
If str=djfs1d2.3
echo $str | cmd?
I get 3
"cmd?" is the command/script that I want
Upvotes: 15
Views: 20959
Reputation: 41
Just found an efficient way to do this in pure Bash with no pipes or explicit conditionals:
# ## Erase all occurrences of pattern from beginning of string:
# * Absolutely anything
# [![:digit:]] Single non-digit character
num="${str##*[![:digit:]]}"
Upvotes: 2
Reputation: 22225
No need to spawn a child process, since you have regexp matching in bash. Assume for example the string
str=a34b56c
Now you can do
if [[ $str =~ ([0-9]+)[^0-9]*$ ]]
then
echo The last number is ${BASH_REMATCH[1]}
else
echo The string "$str" does not contain digits
fi
The trick here is putting parenthesis around that part of the pattern which makes up the number. This allows you to pick up the number using ${BASH_REMATCH[1]}
.
Upvotes: 1
Reputation: 27726
Get all numbers from a string:
grep -Eo '[0-9]+'
Get last number from a string:
grep -Eo '[0-9]+' | tail -1
(Expanding on George's answer a bit..)
-E
means extended regex-o
means print each matching part on a separate lineUpvotes: 3
Reputation: 92854
Short gawk approach (for multiple variables):
echo "$str1 $str2 $str3 $str4 " | awk -v FPAT="[0-9]+ " '{for(i=1;i<=NF;i++) print "str"i": "$i}'
The output:
str1: 2
str2: 3
str3: 45
str4: 8
FPAT="[0-9]+ "
- a regexp that matches the fields, instead of matching the field separatorAs you have changed your initial condition:
For one single string it would be even simpler:
echo djfs1d2.3 | awk -v FPAT="[0-9]+" '{print $NF}'
3
Upvotes: 2
Reputation: 19982
You can use grep
with
rev <<< "$str" | grep -Eo "[0-9]*" | head -1 |rev
EDIT:
rev
is not needed when I use tail -1
but the head/tail are overdone when you just add the end-of-line marker $
like @Vasiliou did (I upvoted his answer). Without rev
and head
the grep
solution is better than sed
.
I deleted my remark "Better is using sed
".
sed -r 's/.*[^0-9]+([0-9]*)$/\1/' <<< "$str"
Upvotes: 4
Reputation: 6335
All you need is grep -Eo '[0-9]+$'
:
gv@debian:~$ echo 234ef85 |grep -Eo '[0-9]+$' ## --> 85
gv@debian:~$ echo 234ef856 |grep -Eo '[0-9]+$' ## --> 856
gv@debian:~$ echo 234ef85d6 |grep -Eo '[0-9]+$' ## --> 6
gv@debian:~$ echo 234ef85d.6 |grep -Eo '[0-9]+$' ## --> 6
gv@debian:~$ echo 234ef85d.6. |grep -Eo '[0-9]+$' ## --> no result
gv@debian:~$ echo 234ef85d.6.1 |grep -Eo '[0-9]+$' ## --> 1
gv@debian:~$ echo 234ef85d.6.1222 |grep -Eo '[0-9]+$' ## --> 1222
Upvotes: 19
Reputation: 241808
You can use parameter expansion with extglob. First, remove the number from the end, then remove what you got from the beginning.
#!/bin/bash
shopt -s extglob
for str in str1s2 djfs1d2.3 fefwfw4rfe45 234ef8 ; do
without_number=${str%%+([0-9])}
echo ${str#$without_number}
done
Upvotes: 9
Reputation: 60058
With awk:
INPUT:
str1 = "str1s2"
str2 = "djfs1d2.3"
str3 = "fefwfw4rfe45"
str4 = "234ef8"
command:
tr = \ < INPUT |
awk '{ match($2,"[0-9]*\"$");
printf "%s: %s\n", $1, substr($2,RSTART,RLENGTH-1); }'
output:
str1: 2
str2: 3
str3: 45
str4: 8
Upvotes: 3