[英]How can I extract, or test, the last field from a string?
I am writing a bash script to test some data. 我正在编写一个bash脚本来测试一些数据。 I created a variable to hold the output of a SQL statement:
我创建了一个变量来保存SQL语句的输出:
$ declare -p data_ck
declare -- data_ck="2019-02-17 TRUE 2019-02-10 23"
I presume my data_ck variable is really just a string rather than an array I can parse into fields. 我想我的data_ck变量实际上只是一个字符串,而不是我可以解析为字段的数组。 So, I next figured out this syntax:
echo ${data_ck[@]:27:2}
因此,我接下来弄清楚了这种语法:
echo ${data_ck[@]:27:2}
which returns "23" in this case. 在这种情况下返回“ 23”。
I could also use: echo "${data_ck[@]: -2:2}"
我还可以使用:
echo "${data_ck[@]: -2:2}"
I want to determine whether my last element, 23, is equal to 30. I have tried different variations of this statement, without success: 我想确定我的最后一个元素23是否等于30。我尝试了此语句的不同变体,但没有成功:
If [ ${data_ck[@]:27:2} != 30 ]; then echo "missing dates"
which returns: -bash: syntax error near unexpected token `then' 返回:-bash:意外令牌'then'附近的语法错误
I get the same result using this method: 使用此方法,我得到相同的结果:
If [ ${data_ck[@]:27:2} -ne 30 ]; then echo "missing dates" fi
I am only slightly familiar with scripting & do not understand what I am doing wrong. 我只是稍微熟悉脚本编写,并且不了解我在做什么错。 Can someone lend a hand?
有人可以伸出援手吗? Thank you!
谢谢!
set -x
declare -- data_ck="2019-02-17 TRUE 2019-02-10 23"
last_field=${data_ck##*[[:space:]]}
[[ $last_field = 30 ]]
...properly emits: ...正确发出:
+ [[ 23 = 30 ]]
...which tells us that ${data_ck##*[[:space:]]}
successfully removed everything up to the last field, allowing the field's contents to be compared to 30
as per your specification. ...这告诉我们
${data_ck##*[[:space:]]}
成功删除了最后一个字段之前的所有内容,从而可以根据您的规范将字段的内容与30
进行比较。
It did this as a parameter expansion , matching and removing the longest-possible string that ends in a space. 它作为参数扩展来执行此操作 ,匹配并删除以空格结尾的最长可能字符串。 (
*[[:space:]]
is a glob-style pattern matching any string ending with a space; ${var##pattern}
expands to the contents of $var
with the longest possible match for pattern
removed from the beginning). (
*[[:space:]]
是一种glob样式的模式,与任何以空格结尾的字符串匹配; ${var##pattern}
扩展为$var
的内容,并且从开头删除的pattern
匹配时间最长。
I can not see all variations of data_ck. 我看不到data_ck的所有变化。 It could be
它可能是
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" )
The value FALSE and the third example makes it impossible to use some fixed offset after converting the array to a string. 值FALSE和第三个示例使将数组转换为字符串后无法使用某些固定偏移量。 You can extract the fourth field with
您可以使用提取第四个字段
if [ "${data_ck[@]:3:1}" = "23" ]; then echo "23 found"; fi
# or shorter
if [ "${data_ck[3]}" = "23" ]; then echo "23 found"; fi
EDIT: When data_ck is a string, you still need to think what is the best way to het your field. 编辑:当data_ck是一个字符串时,您仍然需要考虑什么是最好的方法来修饰您的字段。 Some possibilities:
一些可能性:
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
Assuming data_ck
is a scalar variable, not an array, based on the result of delcare -p data_ck
, you can just say: 根据
delcare -p data_ck
的结果,假设data_ck
是一个标量变量,而不是一个数组,您可以这样说:
data_ck="2019-02-17 TRUE 2019-02-10 23"
if [[ ${data_ck: -2:2} != 30 ]]; then
echo "missing dates"
fi
The following still works but is mostly superfluous: 以下内容仍然有效,但基本上是多余的:
if [[ ${data_ck[@]: -2:2} != 30 ]]; then
echo "missing dates"
fi
As @chepner points out, ${data_ck[@]}
here is evaluated as ${data_ck[0]}
and is equivalent to $data_ck
in the context. 正如@chepner所指出的,此处的
${data_ck[@]}
被评估为${data_ck[0]}
,在上下文中等效于$data_ck
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.