如何逐个单词遍历字符串,然后使用不同的delimeter遍历这些单词(在bash中)



如果我有以下字符串:

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工作得快得多。。。

甚至三个连续的readIFS=- read year month day <<<$date将比使用bash的正则表达式保持更快更少的CPU加热器

相关内容

  • 没有找到相关文章

最新更新