如何在Bash中拆分字符串?

时间:2016-01-29 13:35:42

标签: bash

我有一个变量x,其中包含一个字符串,如" 2025-12-13-04-32 Hello StackOverflow程序员"。

如何将其拆分为多个变量:

d=2015
m=12
dy=13 
h=04
mi=32 
t="Hello StackOverflow programmers"

4 个答案:

答案 0 :(得分:10)

单个read命令可以

input='2025-12-13-04-32 Hello stackoverflow programmers'

IFS='- ' read -r d m dy h mi t <<<"$input"

注意:<<<是一个所谓的here-string,它允许通过stdin提供与多行相关的常规字符串 [变量] { {3}}(以<<EOF开头的东西)。这是echo "$input" | IFS='- ' read ...

的更短,更有效的替代方案
  • IFS='- '会导致读取通过空格或-将输入行拆分为令牌。
  • 即使这通常也会将字符串'Hello stackoverflow programmers'分解为3个令牌,但它不在此处,因为read会将余下分配给指定的最后一个变量,以防没有足够的变量来匹配生成的标记;因此,变量$t会根据需要接收'Hello stackoverflow programmers'

打印结果,请使用以下命令:

请注意,${!name}here-doc的一个实例 - 通过包含其名称的另一个变量访问变量。 功能

names=( d m dy h mi t )
for name in "${names[@]}"; do
  printf '%s=%s\n' "$name" "${!name}"
done

这会产生:

d=2025
m=12
dy=13
h=04
mi=32
t=Hello stackoverflow programmers

关于方法选择的说明:

  • read非常适合基于一组文字分隔符字符的基于字段的解析(需要注意的是非空白分隔符的每个实例.count)。
    • 使用read -ra,您甚至可以将所有令牌读入数组,而无需事先知道令牌的数量。
  • 要获得更灵活的解析(基于已知数量的令牌),请考虑将=~与正则表达式一起使用,如variable indirection中所述。

答案 1 :(得分:5)

使用Bash正则表达式:

#!/bin/bash
s='2025-12-13-04-32 Hello stackoverflow programmers'
pat="([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)[[:space:]]*(.*)"
[[ $s =~ $pat ]]
echo "${BASH_REMATCH[1]}"
echo "${BASH_REMATCH[2]}"
echo "${BASH_REMATCH[3]}"
echo "${BASH_REMATCH[4]}"
echo "${BASH_REMATCH[5]}"
echo "${BASH_REMATCH[6]}"

输出:

2025
12
13
04
32
Hello stackoverflow programmers

答案 2 :(得分:1)

要自动将空格分隔的值分配给变量名,您可以这样做:

x="2025-12-13-04-32 Hello stackoverflow programmers"
read -r d m dy h mi <<< "$x"

但是由于字符串的开头包含破折号( - ),您首先必须用空格替换它们:

x="2025-12-13-04-32 Hello stackoverflow programmers"
x="$(echo "$x" | sed 's/-/ /g')"
read -r d m dy h mi <<< "$x"

仍然需要调整变量名称的数量; - )

我想说这就是你想要的:

x="2025-12-13-04-32 Hello stackoverflow programmers"                                                                                        
x="$(echo "$x" | tr '-' ' ')"                                                                                                               
read -r d m dy h mi t <<< "$x"                                                                                                          
echo $d
2025
echo $m
12
echo $dy
13
echo $h 
04
echo $mi
32
echo $t
Hello stackoverflow programmers

答案 3 :(得分:0)

使用参数替换和declare

#!/bin/bash
x="2025-12-13-04-32 Hello stackoverflow programmers"

Shift () {
    declare -g "$1=${copy%%-*}"
    copy=${copy#*-}
}

copy=$x

for var in d m dy h mi ; do
    Shift $var
done

mi=${mi%% *} # Remove the message
t=${copy#* }

for var in d m dy h mi t ; do
    echo $var ${!var}
done