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 变量中值之间的间距有一些奇怪的字符?

希望有人能赐教

  1. 不要对 awk 或未导出的 shell 变量使用所有大写名称,以避免与内置变量和其他原因发生冲突,例如有关 shell 个问题,请参阅 Correct Bash and shell script variable capitalization

  2. 当输入是 总是在标记值对中。

  3. 有通用代码的时候放上 在一个函数中,不要重复多次——据我们所知 代码中可能存在控制字符或其他问题 一个标签值。

首先更改代码以使用简单的查找函数:

$ 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