如果我有以下字符串:
1234-56-78 17:38:00,00 [main]
我想隔离第二个"单词">
17:38:00,00
然后解析这个词(显然是一个时间戳)来隔离17和38,并将它们放在变量中,我该怎么做?我尝试了以下方法,以获得时间:
stampLine="1234-56-78 17:38:00,00 [main]"
array=("$stampLine")
fullStamp=${array[1]}
IFS=':' read -ra splitStamp <<< $fullStamp
stampArray=($splitStamp)
x=${stampArray[0]}
echo ${x#0} # to strip leading zeroes
以及:
declare -i index
for item in $array; do
if [ index == 1 ]; then
fullStamp=$item
IFS=':' read -ra splitStamp <<< $fullStamp
stampArray=($splitStamp)
x=${stampArray[0]}
echo ${x#0} # to strip leading zeroes
fi
done
但他们两个都失败了,这让我来到了这里。如果有人能回答这个问题和/或解释我遗漏了什么,我将不胜感激
您让它变得不必要的复杂。这应该足够了:
stampLine="1234-56-78 17:38:00,00 [main]"
read date time tag <<< "${stampLine}"
IFS=: read hours minutes seconds <<< "${time}"
echo ${hours}
echo ${minutes}
当然,如果你只想在一步中完成,这是可行的,因为IFS
是一组用于分词的字符,而不仅仅是一个字符:
IFS=" -:" read x x x hours minutes x <<< "${stampLine}"
如果你真的关心其他值,那么需要在它们的位置使用其他变量,但如果你不关心,让shell重用一个"伪"变量是有用的。。。
您第一次尝试的片段:
stampLine="1234-56-78 17:38:00,00 [main]" array=("$stampLine")
。。。不执行您想要的操作,因为您引用了$stampLine
的扩展,从而防止扩展受到分词的影响。如果删除第二行中的引号(如果$IFS
有一个合适的值,例如其默认值),则$array
将初始化为三元素数组。
此处:
fullStamp=${array[1]} IFS=':' read -ra splitStamp <<< $fullStamp
。。。使用内置的read
和一个here字符串是相当重量级的。我想重点是本地化$IFS
的修改值,但您可以通过其他方式来实现。例如,您可以将原始值保存在另一个变量中,然后恢复它。不过,就我个人而言,我可能倾向于用$IFS
:的local
副本声明一个函数
split_HMS() {
local IFS=':'
splitStamp=($1)
}
# ...
fullStamp=${array[1]}
split_HMS $fullStamp
您的第二个例子遇到了一个额外的问题,即尽管您声明了变量$index
,但从未为其分配任何值。因此,测试[ $index == 1 ]
永远不会成功。
特别是为了回答您的问题,
[如何]我想隔离第二个"单词"[…],然后解析这个词(显然是一个时间戳)将17和38和把它们放在变量中[…]?
我可以这样组装部件:
parseTime() {
local IFS=':'
local hms=($2)
hour=${hms[0]#0}
minute=${hms[1]#0}
}
stampLine="1234-56-78 17:08:00,00 [main]"
parseTime $stampLine
echo "hour: $hour"
echo "minute: $minute"
输出:
hour: 17
minute: 8
除了twalberg的正确答案外,我建议这样做:
捷径
stampLine="1234-56-78 17:38:00,00 [main]"
IFS=$' nt:' read day hre min sec foo <<<"$stampLine"
echo $day
1234-56-78
echo $hre
17
echo $min
38
echo $sec
00,00
echo $foo
[main]
当然,在第二行,IFS
可能是=' :'
,但我更喜欢这样做,以避免导致换行或不需要的选项卡,这可能会使read
工作错误。
台阶细节方式
stampLine="1234-56-78 17:38:00,00 [main]"
read date time foo <<<$stampLine
IFS=:, read hrs min sec frac <<<$time
echo $foo
[main]
echo $time
17:38:00,00
echo $frac
00
echo $sec
00
echo $min
38
echo $hrs
17
关于bash regex的一句话
对于这种用法,有两个成功的read
(如第二个示例)将比使用[[ "$stampLine" =~ ... ]]
bashregex工作得快得多。。。
甚至三个连续的read
和IFS=- read year month day <<<$date
将比使用bash的正则表达式保持更快或更少的CPU加热器。