Bash 如何从字符串中提取或测试最后一个字段?
我正在编写一个bash脚本来测试一些数据。我创建了一个变量来保存SQL语句的输出:Bash 如何从字符串中提取或测试最后一个字段?,bash,shell,unix,Bash,Shell,Unix,我正在编写一个bash脚本来测试一些数据。我创建了一个变量来保存SQL语句的输出: $ declare -p data_ck declare -- data_ck="2019-02-17 TRUE 2019-02-10 23" 我假设我的数据\u ck变量实际上只是一个字符串,而不是可以解析为字段的数组。所以,我接下来想出了这个语法:echo${data\u ck[@]:27:2} 在本例中返回“23” 我还可以使用:echo“${data\u ck[@]:-2:2}” 我想确定最后
$ declare -p data_ck
declare -- data_ck="2019-02-17 TRUE 2019-02-10 23"
我假设我的数据\u ck变量实际上只是一个字符串,而不是可以解析为字段的数组。所以,我接下来想出了这个语法:echo${data\u ck[@]:27:2}
在本例中返回“23”
我还可以使用:echo“${data\u 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
我只是稍微熟悉脚本&不明白我做错了什么。有人能帮忙吗?谢谢大家! 我看不到数据的所有变化。可能是
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
编辑:
当数据是一个字符串时,您仍然需要考虑用什么样的方式来填充字段。一些可能性:
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
我看不到数据的所有变化。可能是
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
编辑:
当数据是一个字符串时,您仍然需要考虑用什么样的方式来填充字段。一些可能性:
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
假设
data\u ck
是基于
delcare-p数据检查的结果,您可以说:
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\u ck[@]}
在这里被评估为
${data\u ck[0]}
与上下文中的$data\u ck
等效。假设data\u ck
是基于
set -x
declare -- data_ck="2019-02-17 TRUE 2019-02-10 23"
last_field=${data_ck##*[[:space:]]}
[[ $last_field = 30 ]]
delcare-p数据检查的结果,您可以说:
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\u ck[@]}
在这里被评估为
${data\u ck[0]}
并且在上下文中等同于$data\u ck
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
进行比较
它这样做是为了匹配并删除以空格结尾的尽可能长的字符串。(*[:space:]
是一个匹配任何以空格结尾的字符串;${var##pattern}
扩展到$var
的内容,从开头删除了与pattern
最长的匹配项)
…正确地发射:
+ [[ 23 = 30 ]]
…这告诉我们,${data#ck##*[:space:][]}
成功删除了最后一个字段的所有内容,允许根据您的规范将该字段的内容与30
进行比较
它这样做是为了匹配并删除以空格结尾的尽可能长的字符串。(
*[:space:]
是一个匹配任何以空格结尾的字符串;${var##pattern}
扩展到$var
的内容,并从开头删除了与pattern
最长的匹配)。data\u-ck
是一个数组。实际上,bash中几乎每个变量都包含一个字符串。请发布declare-p data\u-ck
的输出。你错过了代码>在fi
之前,即如果。。。;然后;fi
。请记住
of[“${….}”引用变量。“declare-p data_-ck”返回:declare--data_-ck=“2019-02-17 TRUE 2019-02-10 23”,并在“fi”之前添加分号语句有效!@KamilCukdata\u ck
不是数组,由declare-p
确认。您可以将数组语法与正则变量一起使用,它将被视为索引为0的单元素数组。如果使用大写的I
,您是否实际使用了?它必须是小写的。为什么使用[@]
如果你的内容不是数组,那它就是数组特定的语法;对于非数组值,它唯一能做的就是混淆读者。data\u ck
是数组。实际上,bash中几乎每个变量都包含一个字符串。请发布declare-p data\u ck
的输出。你错过了fi
之前的;
,即if…;然后…;fi
。记住对[“${…}”的引用变量。“declare-p data_-ck”返回:declare--data_-ck=“2019-02-17 TRUE 2019-02-10 23”,并在我的“fi”前面添加分号语句有效!@KamilCukdata\u ck
不是数组,由declare-p
确认。您可以将数组语法与正则变量一起使用,它将被视为索引为0的单元素数组。如果使用大写的I
,您是否实际使用了?它必须是小写的。为什么使用[@]
如果你的内容不是数组,那就不必担心了?它是数组特有的语法;对于非数组值,它唯一能做的就是让读者感到困惑。我的理解是,如果我的变量真的是数组,我可以使用[@]:3:1或[3]。但是,它不是数组,它只是一个长字符串。这就是我使用“字符位置”的原因,意思是[@]:27:2。@CarCrazyBen使用[@]
(和[1]
等)来控制提取数组的哪些元素。不要将它们与非数组变量一起使用。充其量,它们会被忽略(但会让试图读取/维护脚本的人感到困惑);最坏的情况是,它们会以不可预测的方式使脚本失败。我的理解是,如果我的变量是真正的数组,我可以使用[@]:3:1或[3]。但是,它不是数组-它只是一个长字符串。这就是为什么我使用“字符位置”,m