如何在shell中拆分字符串并获取最后一个字段

时间:2010-07-01 23:29:39

标签: bash split tokenize cut

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

18 个答案:

答案 0 :(得分:370)

您可以使用string operators

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

贪婪地修剪从前面到':'的所有内容。

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }

答案 1 :(得分:326)

另一种方法是在cut之前和之后反转:

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

这样可以很容易地获得最后一个字段,或从末尾开始编号的任何字段范围。

答案 2 :(得分:66)

使用cut获取最后一个字段很困难,但这里是awk和perl中的(一组)解决方案

$ echo 1:2:3:4:5 | awk -F: '{print $NF}'
5
$ echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
5

答案 3 :(得分:26)

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

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

细分 - 在行的末尾找到所有字符而不是分隔符([^:])($)。 -o只​​打印匹配的部分。

答案 4 :(得分:18)

一种方式:

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(版本&gt; = 3.2)正则表达式:

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}

答案 5 :(得分:10)

如果您想使用 cut,可以尝试这样的操作:

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

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

echo " 1:2:3:4:5" | grep -o '[^:]*$'

答案 6 :(得分:9)

$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

只需将分隔符翻译成换行符,然后选择tail -1的最后一个条目。

答案 7 :(得分:6)

使用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

答案 8 :(得分:4)

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

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

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

检查string manipulation in bash

答案 9 :(得分:3)

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

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

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

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

答案 10 :(得分:2)

echo "a:b:c:d:e"|xargs -d : -n1|tail -1

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

答案 11 :(得分:2)

使用Bash。

$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo  \$${#}
0

答案 12 :(得分:1)

for x in `echo $str | tr ";" "\n"`; do echo $x; done

答案 13 :(得分:1)

使用read builtin的解决方案:

x <- do.call(merge, rlist)

或者,使它更通用:

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

答案 14 :(得分:1)

对于那些熟悉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代码。

答案 15 :(得分:0)

答案可能有点晚,尽管一个简单的解决方案是反转输入字符串的顺序。无论长度如何,这都将使您始终获得最后一个项目。

[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5

但是要特别注意的是,如果使用此方法并且数字大于1位(或者在任何情况下大于1个字符),则将需要在管道输出上运行另一个“ rev”命令。

[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24

希望我能帮上忙,欢呼

答案 16 :(得分:0)

如果您喜欢python并可以选择安装软件包,则可以使用this python utility

# install pythonp
pythonp -m pip install pythonp

echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5

答案 17 :(得分:0)

sed中的正则表达式匹配很贪心(总是到最后一次出现),您可以在这里利用它来发挥自己的优势:

$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5