我有一个变量x
,其中包含一个字符串,如" 2025-12-13-04-32 Hello StackOverflow程序员"。
如何将其拆分为多个变量:
d=2015
m=12
dy=13
h=04
mi=32
t="Hello StackOverflow programmers"
答案 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