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

cd1*_*cd1 279 bash split cut tokenize

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

Ste*_*hen 398

您可以使用字符串运算符:

$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
Run Code Online (Sandbox Code Playgroud)

从the:This This This This This This This This trim trim trim trim trim trim.

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }
Run Code Online (Sandbox Code Playgroud)

  • 如何在最后一个分隔符之前保留该部分?显然是使用`$ {foo%:*}`.`#` - 从一开始; `%` - 从结尾.`#`,`%` - 最短匹配; `##`,`%%` - 最长的匹配. (11认同)
  • 你怎么会这样做呢?回应'1:2:3:4:'? (9认同)
  • 虽然这对于给定的问题是有效的,但如果字符串是"1:2:3:4:5:",William下面的答案(http://stackoverflow.com/a/3163857/520162)也会返回"5". (使用字符串运算符时会产生空结果).在解析可能包含(或不包含)整理`/`字符的路径时,这尤其方便. (7认同)
  • @Putnik,该命令将`pwd`视为变量。尝试`dir = $(pwd); 回声$ {dir ## * /}`。为我工作! (2认同)

a3n*_*3nm 338

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

$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
Run Code Online (Sandbox Code Playgroud)

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

  • 这个答案很好,因为它使用了'cut',作者(大概)已经熟悉了.另外,我喜欢这个答案因为*我*正在使用'cut'并且有这个确切的问题,因此通过搜索找到这个帖子. (17认同)
  • 为使用空格作为分隔符的人们提供一些剪切和粘贴的素材:`echo"1 2 3 4"| 转| cut -d"" - f1 | rev` (6认同)
  • 转| cut -d -f1 | rev很聪明!谢谢!帮了我一堆(我的用例是rev | -d'' - f 2- | rev (2认同)

Wil*_*ell 71

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

  • 这个解决方案的优势超过了公认的答案:它还匹配包含或不包含整理`/`字符的路径:`/ a/b/c/d`和`/ a/b/c/d /`yield处理`pwd |时的结果相同(`d`)awk -F /'{print $ NF}'`.在"/ a/b/c/d /"的情况下,接受的答案会导致空结果 (5认同)

Nic*_*ott 28

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

$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
Run Code Online (Sandbox Code Playgroud)

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


Pau*_*ce. 18

单程:

var1="1:2:3:4:5"
var2=${var1##*:}
Run Code Online (Sandbox Code Playgroud)

另一个,使用数组:

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

另一个有阵列:

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

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

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


Abd*_*_98 11

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

echo "1:2:3:4:5" | cut -d ":" -f5
Run Code Online (Sandbox Code Playgroud)

你也可以grep像这样使用try :

echo " 1:2:3:4:5" | grep -o '[^:]*$'
Run Code Online (Sandbox Code Playgroud)


小智 10

$ echo "a b c d e" | tr ' ' '\n' | tail -1
e
Run Code Online (Sandbox Code Playgroud)

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

  • 如果最后一项包含`\n`,它将失败,但在大多数情况下是最易读的解决方案。 (2认同)

Raf*_*ael 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
Run Code Online (Sandbox Code Playgroud)


021*_*021 5

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

 basename $(echo "a:b:c:d:e" | tr ':' '/')
Run Code Online (Sandbox Code Playgroud)

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

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