【发布时间】:2021-04-30 12:36:13
【问题描述】:
我发现了一个我无法解决的奇怪问题。
我需要在一个变量中提取一些值,这些值在一个字符串之后。
本例中的变量名是: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 变量中的值之间的间距有一些奇怪的字符?
希望有人能启发我。
【问题讨论】:
-
你为什么不直接做
ATTUPSTREAM=$(awk '/NewUpstreamAttenuation/{print $2}' <<< $DSLTATE)?如果您将搜索字符串替换为相应的值,这也适用于所有其他值。 -
不要对 awk 或未导出的 shell 变量使用全部大写的名称,以避免与内置变量和其他原因发生冲突,例如有关 shell 问题,请参阅 stackoverflow.com/questions/673055/…。
-
这是我评论中的错字。
-
在 OPs 代码中也有错字 - 我强烈怀疑 @rowboat 解决了这个问题。
-
@accdias 我几乎不是 shell 脚本的大师,但这是我的反馈 FWIW - 它使用了一个不可移植的字符串化构造
<<<并且 OP 没有告诉我们他们是哪个 shell使用这样可能对他们不起作用,如果一个标签是另一个标签的一部分,它会失败,例如假设您在输入中有NewUpstreamAttenuation和NewUpstreamAttenuationMax- 该脚本将打印这两个值,并且(可能不太可能)如果任何标签包含正则表达式元字符,例如The.Max,那么你需要确保逃脱它们。