BASH 提取变量 Not 文件中字符串后的值
BASH extract value after string in variable Not file
我发现了一个我无法解决的奇怪问题。
我需要在变量中提取一些值,这些值在字符串之后。
本例中变量的名称为:DSLSTATE
这是其中值的示例:
NewEnable 1
NewStatus Up
NewDataPath Fast
NewUpstreamCurrRate 21598
NewDownstreamCurrRate 170788
NewUpstreamMaxRate 25692
NewDownstreamMaxRate 170788
NewUpstreamNoiseMargin 90
NewDownstreamNoiseMargin 60
NewUpstreamAttenuation 150
NewDownstreamAttenuation 170
NewATURVendor 41564d00
NewATURCountry 0400
NewUpstreamPower 486
NewDownstreamPower 514
这不是数组。
提取我想要的价值:
ATTUPSTREAM=$(echo "$DSLTATE" | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamAttenuation") print $(I+1)}')
在此示例中,该值应为 150,但它始终为空。
奇怪的是,我可以使用相同的命令从同一个变量中提取所有值,但示例之一除外。
如果我在终端上执行相同的命令它工作,在脚本中不起作用。
这里是脚本的摘录:
UPSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamCurrRate") print $(I+1)}')
DOWNSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewDownstreamCurrRate") print $(I+1)}')
ATTUPSTREAM=$(echo $DSLTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamAttenuation") print $(I+1)}')
ATTDOWNSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewDownstreamAttenuation") print $(I+1)}')
SNRUPSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamNoiseMargin") print $(I+1)}')
SNRDOWNSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewDownstreamNoiseMargin") print $(I+1)}')
这些是结果:
ATTUPSTREAM=
ATTDOWNSTREAM=170
SNRUPSTREAM=40
SNRDOWNSTREAM=50
也许在 DSLSTATE 变量中值之间的间距有一些奇怪的字符?
希望有人能赐教
不要对 awk 或未导出的 shell 变量使用所有大写名称,以避免与内置变量和其他原因发生冲突,例如有关 shell 个问题,请参阅 Correct Bash and shell script variable capitalization。
当输入是
总是在标记值对中。
有通用代码的时候放上
在一个函数中,不要重复多次——据我们所知
代码中可能存在控制字符或其他问题
一个标签值。
首先更改代码以使用简单的查找函数:
$ tag2val() { echo "$DSLSTATE" | awk -v tag="" '==tag { print }'; }
$ tag2val NewDataPath
Fast
$ tag2val NewUpstreamAttenuation
150
如果您仍有问题,请告诉我们。如果您这样做,请编辑您的问题以显示 echo "$DSLSTATE" | cat -Ev
.
的输出
如果您使用 Bash,另一个选项可以将 DSLSTATE
转换为关联数组。之后根据key取值就更简单了:
#!/bin/bash
DSLSTATE='NewEnable 1
NewStatus Up
NewDataPath Fast
NewUpstreamCurrRate 21598
NewDownstreamCurrRate 170788
NewUpstreamMaxRate 25692
NewDownstreamMaxRate 170788
NewUpstreamNoiseMargin 90
NewDownstreamNoiseMargin 60
NewUpstreamAttenuation 150
NewDownstreamAttenuation 170
NewATURVendor 41564d00
NewATURCountry 0400
NewUpstreamPower 486
NewDownstreamPower 514'
declare -A kv
while read k v; do
kv[$k]=$v
done <<< $DSLSTATE
echo "NewDownstreamPower: ${kv[NewDownstreamPower]}"
上面的代码将导致:
NewDownstreamPower: 514
我发现了一个我无法解决的奇怪问题。
我需要在变量中提取一些值,这些值在字符串之后。
本例中变量的名称为:DSLSTATE
这是其中值的示例:
NewEnable 1
NewStatus Up
NewDataPath Fast
NewUpstreamCurrRate 21598
NewDownstreamCurrRate 170788
NewUpstreamMaxRate 25692
NewDownstreamMaxRate 170788
NewUpstreamNoiseMargin 90
NewDownstreamNoiseMargin 60
NewUpstreamAttenuation 150
NewDownstreamAttenuation 170
NewATURVendor 41564d00
NewATURCountry 0400
NewUpstreamPower 486
NewDownstreamPower 514
这不是数组。
提取我想要的价值:
ATTUPSTREAM=$(echo "$DSLTATE" | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamAttenuation") print $(I+1)}')
在此示例中,该值应为 150,但它始终为空。
奇怪的是,我可以使用相同的命令从同一个变量中提取所有值,但示例之一除外。 如果我在终端上执行相同的命令它工作,在脚本中不起作用。
这里是脚本的摘录:
UPSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamCurrRate") print $(I+1)}')
DOWNSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewDownstreamCurrRate") print $(I+1)}')
ATTUPSTREAM=$(echo $DSLTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamAttenuation") print $(I+1)}')
ATTDOWNSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewDownstreamAttenuation") print $(I+1)}')
SNRUPSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewUpstreamNoiseMargin") print $(I+1)}')
SNRDOWNSTREAM=$(echo $DSLSTATE | awk '{for (I=1;I<NF;I++) if ($I == "NewDownstreamNoiseMargin") print $(I+1)}')
这些是结果:
ATTUPSTREAM=
ATTDOWNSTREAM=170
SNRUPSTREAM=40
SNRDOWNSTREAM=50
也许在 DSLSTATE 变量中值之间的间距有一些奇怪的字符?
希望有人能赐教
不要对 awk 或未导出的 shell 变量使用所有大写名称,以避免与内置变量和其他原因发生冲突,例如有关 shell 个问题,请参阅 Correct Bash and shell script variable capitalization。
当输入是 总是在标记值对中。
有通用代码的时候放上 在一个函数中,不要重复多次——据我们所知 代码中可能存在控制字符或其他问题 一个标签值。
首先更改代码以使用简单的查找函数:
$ tag2val() { echo "$DSLSTATE" | awk -v tag="" '==tag { print }'; }
$ tag2val NewDataPath
Fast
$ tag2val NewUpstreamAttenuation
150
如果您仍有问题,请告诉我们。如果您这样做,请编辑您的问题以显示 echo "$DSLSTATE" | cat -Ev
.
如果您使用 Bash,另一个选项可以将 DSLSTATE
转换为关联数组。之后根据key取值就更简单了:
#!/bin/bash
DSLSTATE='NewEnable 1
NewStatus Up
NewDataPath Fast
NewUpstreamCurrRate 21598
NewDownstreamCurrRate 170788
NewUpstreamMaxRate 25692
NewDownstreamMaxRate 170788
NewUpstreamNoiseMargin 90
NewDownstreamNoiseMargin 60
NewUpstreamAttenuation 150
NewDownstreamAttenuation 170
NewATURVendor 41564d00
NewATURCountry 0400
NewUpstreamPower 486
NewDownstreamPower 514'
declare -A kv
while read k v; do
kv[$k]=$v
done <<< $DSLSTATE
echo "NewDownstreamPower: ${kv[NewDownstreamPower]}"
上面的代码将导致:
NewDownstreamPower: 514