如何从字符串中提取或测试最后一个字段?

时间:2019-02-18 18:59:52

标签: bash shell unix

我正在编写一个bash脚本来测试一些数据。我创建了一个变量来保存SQL语句的输出:

$ declare -p data_ck
declare -- data_ck="2019-02-17  TRUE    2019-02-10  23"

我认为我的 data_ck 变量实际上只是一个字符串,而不是我可以解析为字段的数组。因此,我接下来想出了以下语法:echo ${data_ck[@]:27:2}

在这种情况下返回“ 23”。

我还可以使用:echo "${data_ck[@]: -2:2}"

我想确定我的最后一个元素23是否等于30。我尝试了此语句的其他变体,但没有成功:

If [ ${data_ck[@]:27:2} != 30 ]; then echo "missing dates"

返回:    -bash:意外令牌'then'附近的语法错误

使用这种方法,我得到相同的结果:

If [ ${data_ck[@]:27:2} -ne 30 ]; then echo "missing dates" fi

我只对脚本略有熟悉,并且不了解我在做什么错。有人可以伸出援手吗?谢谢!

3 个答案:

答案 0 :(得分:2)

set -x
declare -- data_ck="2019-02-17  TRUE    2019-02-10  23"
last_field=${data_ck##*[[:space:]]}
[[ $last_field = 30 ]]

...正确发射:

+ [[ 23 = 30 ]]

...这告诉我们${data_ck##*[[:space:]]}成功删除了最后一个字段之前的所有内容,从而可以根据您的规范将字段的内容与30进行比较。

它以parameter expansion的形式执行,匹配并删除了以空格结尾的最长可能字符串。 (*[[:space:]]是一个glob-style pattern,它匹配任何以空格结尾的字符串; ${var##pattern}扩展到$var的内容,其中pattern的最长匹配项已从列表中删除。开始)。

答案 1 :(得分:1)

我看不到data_ck的所有变体。可能是

data_ck=( 2019-02-17 TRUE 2019-02-10 23 )
data_ck=( 2019-02-17 FALSE 2019-02-10 23 )
data_ck=( 2019-02-17 TRUE 2019-02-10 301233 0 )
data_ck=( "2019-02-17 TRUE 2019-02-10 23" )

值FALSE和第三个示例使将数组转换为字符串后无法使用某些固定偏移量。 您可以使用

提取第四个字段
if [ "${data_ck[@]:3:1}" = "23" ]; then echo "23 found"; fi
# or shorter
if [ "${data_ck[3]}" = "23" ]; then echo "23 found"; fi

编辑: 当data_ck是一个字符串时,您仍然需要考虑什么是最好的方式来修饰您的字段。一些可能性:

echo "${data_ck}" | sed 's/.* //'    # Get everything after last space
echo "${data_ck}" | sed -r 's/.* ([^ ]+) */\1/' # get last field in string ending with spaces
echo "${data_ck}" | cut -d" " -f4    # Get 4th field
echo "${data_ck}" | awk '{print $4}' # 4th field where 2 spaces count as 1 delimiter

答案 2 :(得分:1)

假设data_ck是标量变量,而不是数组,基于 delcare -p data_ck的结果,您可以说:

data_ck="2019-02-17 TRUE 2019-02-10 23"
if [[ ${data_ck: -2:2} != 30 ]]; then
    echo "missing dates"
fi

以下内容仍然有效,但基本上是多余的:

if [[ ${data_ck[@]: -2:2} != 30 ]]; then
    echo "missing dates"
fi

正如@chepner指出的那样,此处的${data_ck[@]}被评估为 ${data_ck[0]},在上下文中等效于$data_ck