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

发布于 2024-09-08 02:27:27 字数 150 浏览 9 评论 0原文

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

Suppose I have the string 1:2:3:4:5 and I want to get its last field (5 in this case). How do I do that using Bash? I tried cut, but I don't know how to specify the last field with -f.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

╰ゝ天使的微笑 2024-09-15 02:27:27

您可以使用字符串运算符

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

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

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

You can use string operators:

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

This trims everything from the front until a ':', greedily.

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }
抚笙 2024-09-15 02:27:27

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

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

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

Another way is to reverse before and after cut:

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

This makes it very easy to get the last but one field, or any range of fields numbered from the end.

转瞬即逝 2024-09-15 02:27:27

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

It's difficult to get the last field using cut, but here are some solutions in awk and perl

echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
滥情哥ㄟ 2024-09-15 02:27:27

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

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

B​​reakdown - 查找行尾 ($) 处除分隔符 ([^:]) 之外的所有字符。 -o 只打印匹配的部分。

Assuming fairly simple usage (no escaping of the delimiter, for example), you can use grep:

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

Breakdown - find all the characters not the delimiter ([^:]) at the end of the line ($). -o only prints the matching part.

蒲公英的约定 2024-09-15 02:27:27

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

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

您也可以使用 grep 尝试如下:

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

You could try something like this if you want to use cut:

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

You can also use grep try like this :

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

何时共饮酒 2024-09-15 02:27:27

一种方法:

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]}

One way:

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

Another, using an array:

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

Yet another with an array:

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

Using Bash (version >= 3.2) regular expressions:

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
梦行七里 2024-09-15 02:27:27
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

只需将分隔符转换为换行符,然后使用 tail -1 选择最后一个条目。

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

Simply translate the delimiter into a newline and choose the last entry with tail -1.

听,心雨的声音 2024-09-15 02:27:27

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

Using 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
可是我不能没有你 2024-09-15 02:27:27

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

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

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

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

There are many good answers here, but still I want to share this one using basename :

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

However it will fail if there are already some '/' in your string.
If slash / is your delimiter then you just have to (and should) use basename.

It's not the best answer but it just shows how you can be creative using bash commands.

凶凌 2024-09-15 02:27:27

如果您的最后一个字段是单个字符,您可以执行以下操作:

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

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

检查 字符串操作bash

If your last field is a single character, you could do this:

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

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

Check string manipulation in bash.

旧城烟雨 2024-09-15 02:27:27

使用 Bash。

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

Using Bash.

$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo  \${#}
0
马蹄踏│碎落叶 2024-09-15 02:27:27

sed 中的正则表达式匹配是贪婪的(总是到最后一次出现),您可以在此处利用它:

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

Regex matching in sed is greedy (always goes to the last occurrence), which you can use to your advantage here:

$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
还不是爱你 2024-09-15 02:27:27
echo "a:b:c:d:e"|xargs -d : -n1|tail -1

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

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

First use xargs split it using ":",-n1 means every line only have one part.Then,pring the last part.

梨涡 2024-09-15 02:27:27

使用 read 内置函数的解决方案:

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

或者,使其更通用:

echo "${fields[-1]}" # prints the last item

A solution using the read builtin:

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

Or, to make it more generic:

echo "${fields[-1]}" # prints the last item
一向肩并 2024-09-15 02:27:27
for x in `echo $str | tr ";" "\n"`; do echo $x; done
for x in `echo $str | tr ";" "\n"`; do echo $x; done
空‖城人不在 2024-09-15 02:27:27

改进 @mateusz-piotrowski 和 @user3133260 答案,

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

首先,tr ':' ' ' -> 然后用空格替换 ':',

然后用 xargs 进行修剪

,tr ' ' '\n' -> 最后将剩余的空格替换为换行符

,tail -1 ->获取最后一个字符串

improving from @mateusz-piotrowski and @user3133260 answer,

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

first, tr ':' ' ' -> replace ':' with whitespace

then, trim with xargs

after that, tr ' ' '\n' -> replace remained whitespace to newline

lastly, tail -1 -> get the last string

羁绊已千年 2024-09-15 02:27:27

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

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

来自 pythonpy 帮助:-x 将 stdin 的每一行视为 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 的 std 库。

For those that comfortable with Python, https://github.com/Russell91/pythonpy is a nice choice to solve this problem.

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

From the pythonpy help: -x treat each row of stdin as x.

With that tool, it is easy to write python code that gets applied to the input.

Edit (Dec 2020):
Pythonpy is no longer online.
Here is an alternative:

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

it contains more boilerplate code (i.e. sys.stdout.read/write) but requires only std libraries from python.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文