这是this问题的后续问题,涉及如何知道字符串中分组数字的数量。
在bash中,
如何找到字符串中最后出现的一组数字? 所以,如果我有
string="123 abc 456"
我会得到
456
如果我有
string="123 123 456"
我仍然会得到
456
答案 0 :(得分:2)
没有外部实用程序(例如sed
,awk
,...
):
$ s="123 abc 456"
$ [[ $s =~ ([0-9]+)[^0-9]*$ ]] && echo "${BASH_REMATCH[1]}"
456
BASH_REMATCH
是一个特殊的数组,其中[[ ... =~ ... ]]
中的匹配项被分配给该数组。
测试代码:
str=("123 abc 456" "123 123 456" "123 456 abc def" "123 abc" "abc 123" "123abc456def")
for s in "${str[@]}"; do
[[ $s =~ ([0-9]+)[^0-9]*$ ]] && echo "$s -> ${BASH_REMATCH[1]}"
done
输出:
123 abc 456 -> 456
123 123 456 -> 456
123 456 abc def -> 456
123 abc -> 123
abc 123 -> 123
123abc456def -> 456
答案 1 :(得分:1)
grep -o '[0-9]\+' file|tail -1
grep -o
仅列出匹配的文本tail -1
仅输出最后一个匹配项好吧,如果您有字符串:
grep -o '[0-9]\+' <<< '123 foo 456 bar' |tail -1
答案 2 :(得分:1)
您可以在Bash中使用正则表达式:
$ echo "$string"
123 abc 456
$ [[ $line =~ (^.*[ ]+|^)([[:digit:]]+) ]] && echo "${BASH_REMATCH[2]}"
456
如果您要捕获456
或abc123def456
之类的无界字符串,则可以执行以下操作:
$ echo "$string"
test456text
$ [[ $string =~ ([[:digit:]]+)[^[:digit:]]*$ ]] && echo "${BASH_REMATCH[1]}"
456
但是,如果您要使用外部工具,请使用awk
。
这里是Bash vs Awk的演示,以获取字符串中的最后一位数字。这些用于带有' '
分隔符的数字,或者用于字符串的结尾或开头的数字。
给出:
$ cat file
456
123 abc 456
123 123 456
abc 456
456 abc
123 456 foo bar
abc123def456
这是一个测试脚本:
while IFS= read -r line || [[ -n $line ]]; do
bv=""
av=""
[[ $line =~ (^.*[ ]+|^)([[:digit:]]+) ]] && bv="${BASH_REMATCH[2]}"
av=$(awk '{for (i=1;i<=NF;i++) if (match($i, /^[[:digit:]]+$/)) last=$i; print last}' <<< "$line")
printf "line=%22s bash=\"%s\" awk=\"%s\"\n" "\"$line\"" "$bv" "$av"
done <file
打印:
line= "456" bash="456" awk="456"
line= "123 abc 456" bash="456" awk="456"
line= "123 123 456" bash="456" awk="456"
line= "abc 456" bash="456" awk="456"
line= "456 abc" bash="456" awk="456"
line= "123 456 foo bar" bash="456" awk="456"
line= "abc123def456" bash="" awk=""
答案 3 :(得分:1)
您可以使用此sed
提取一行中的最后一个数字:
sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/'
示例:
sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 abc 456'
456
sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 456 foo bar'
456
sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 123 456'
456
sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 x'
123
RegEx详细信息:
(.*[^0-9]|^)
:开头匹配0个或更多字符,然后以非数字或行开头。([0-9]+)
:匹配1个以上的数字并捕获到#2组.*
:匹配其余字符直到行尾\2
:将其替换为后向引用2(我们在组2中捕获的内容)答案 4 :(得分:1)
使用纯Bash的另一种方法:
shopt -s extglob # enable extended globbing - for *(...)
tmp=${string%%*([^0-9])} # remove non-digits at the end
last_digits=${tmp##*[^0-9]} # remove everything up to the last non-digit
printf '%s\n' "$last_digits"
答案 5 :(得分:0)
这是参数扩展的好工作:
$ string="123 abc 456"
$ echo ${string##* }
456
答案 6 :(得分:0)
一个简单的答案gawk
:
echo "$string" | gawk -v RS=" " '/^[[:digit:]]+$/ { N = $0 } ; END { print N }'
使用RS=" "
,我们将每个字段作为单独的记录读取。
然后我们保留找到的最后一个数字并打印出来。
$ string="123 abc 456 abc"
$ echo "$string" | gawk -v RS=" " '/^[[:digit:]]+$/ { N = $0 } ; END { print N }'
456