340

假设我有字符串1:2:3:4:5并且我想获取它的最后一个字段(5在这种情况下)。我如何使用 Bash 做到这一点?我试过cut了,但我不知道如何指定最后一个字段-f

4

17 回答 17

506

您可以使用字符串运算符

$ foo=1:2:3:4:5
$ echo ${foo##*:}
5

这会贪婪地修剪从前面到“:”的所有内容。

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }
于 2010-07-02T00:05:40.870 回答
378

另一种方法是前后颠倒cut

$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef

这使得获取最后一个字段或从末尾编号的任何字段范围变得非常容易。

于 2012-02-03T08:39:53.820 回答
91

使用cut很难得到最后一个字段,但是这里有一些awk和perl中的解决方案

echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
于 2010-07-02T07:09:21.627 回答
35

假设使用相当简单(例如,没有转义分隔符),您可以使用 grep:

$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5

细分 - 在行尾 ($) 查找除定界符 ([^:]) 之外的所有字符。-o 只打印匹配的部分。

于 2010-07-01T23:39:25.163 回答
19

单程:

var1="1:2:3:4:5"
var2=${var1##*:}

另一个,使用数组:

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}

另一个带有数组的:

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}

使用 Bash(版本 >= 3.2)正则表达式:

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
于 2010-07-02T00:05:22.683 回答
18

如果你想使用,你可以尝试这样的事情cut

echo "1:2:3:4:5" | cut -d ":" -f5

您也可以grep像这样使用尝试:

echo " 1:2:3:4:5" | grep -o '[^:]*$'
于 2021-02-06T09:40:57.407 回答
13
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

只需将分隔符转换为换行符并选择最后一个条目tail -1

于 2013-12-24T19:04:53.447 回答
7

使用sed

$ echo '1:2:3:4:5' | sed 's/.*://' # => 5

$ echo '' | sed 's/.*://' # => (empty)

$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c

$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c
于 2016-11-10T10:09:35.020 回答
3

如果您的最后一个字段是单个字符,您可以这样做:

a="1:2:3:4:5"

echo ${a: -1}
echo ${a:(-1)}

检查bash 中的字符串操作

于 2013-11-13T16:10:40.563 回答
3

这里有很多很好的答案,但我仍然想使用basename分享这个:

 basename $(echo "a:b:c:d:e" | tr ':' '/')

但是,如果您的字符串中已经有一些“/”,它将失败。如果斜杠 / 是您的分隔符,那么您只需要(并且应该)使用 basename。

这不是最好的答案,但它只是展示了如何使用 bash 命令发挥创造力。

于 2016-04-26T11:33:56.537 回答
2

使用 Bash。

$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo  \$${#}
0
于 2010-07-02T01:16:16.097 回答
1
echo "a:b:c:d:e"|xargs -d : -n1|tail -1

首先使用 xargs 使用“:”拆分它,-n1 表示每一行只有一个部分。然后,pring 最后一部分。

于 2016-12-07T06:51:26.193 回答
1

使用 read 内置的解决方案:

IFS=':' read -a fields <<< "1:2:3:4:5"
echo "${fields[4]}"

或者,使其更通用:

echo "${fields[-1]}" # prints the last item
于 2017-11-24T19:27:11.330 回答
0
for x in `echo $str | tr ";" "\n"`; do echo $x; done
于 2012-06-22T02:55:00.757 回答
0

正则表达式匹配sed是贪婪的(总是到最后一次出现),你可以在这里使用它来发挥你的优势:

$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
于 2019-01-29T15:12:35.887 回答
0

对于那些熟悉 Python 的人来说,https://github.com/Russell91/pythonpy是解决这个问题的不错选择。

$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'

从 pythonpy 帮助:-x treat each row of stdin as x.

使用该工具,可以轻松编写应用于输入的 Python 代码。

编辑(2020 年 12 月):Pythonpy 不再在线。这是一个替代方案:

$ echo "a:b:c:d:e" | python -c 'import sys; sys.stdout.write(sys.stdin.read().split(":")[-1])'

它包含更多样板代码(即sys.stdout.read/write),但只需要来自 python 的标准库。

于 2018-02-19T15:50:21.517 回答
-1

如果你喜欢 python 并且可以选择安装包,你可以使用这个 python 实用程序

# install pythonp
pythonp -m pip install pythonp

echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5
于 2019-01-05T18:04:19.853 回答