我有一个在带有 BusyBox 的嵌入式 Linux 上运行的系统。有一个 YAML 配置文件“cfg.yaml”,其中包含如下内容:
range:
tcpportmin: 10000
tcpportmax: 20000
我需要从文件中提取一些值。例如,“tcpportmin”参数的值,即“10000”。我通过脚本来做到这一点。
当我在一个小“cfg.yaml”文件上执行这段代码时,一切顺利:
RANGE=`cat cfg.yaml`
TCP_PORT_MIN=`echo $RANGE | sed "s/.*tcpportmin: \([[:digit:]]*\).*/\1/"`
echo $TCP_PORT_MIN
# Output:
# 10000
但真实的“cfg.yaml”文件的大小为数百千字节,在这种情况下会引发错误:
/test.sh: line 211: echo: Argument list too long
如果我直接对文件应用相同的 sed 命令,结果是错误的:
TCP_PORT_MIN=`sed "s/.*tcpportmin: \([[:digit:]]*\).*/\1/" cfg.yaml`
echo $TCP_PORT_MIN
# Output:
# range: 10000 tcpportmax: 20000
如果我尝试在一行中使用多个 sed 命令,结果为空:
TCP_PORT_MIN=`sed -e "s/.*tcpportmin: \([[:digit:]]*\).*/\1/" -e "s/.*\([[:digit:]]*\).*/\1/p" cfg.yaml`
echo $TCP_PORT_MIN
# Output:
# <Nothing>
仅供参考,我的系统上 sed 命令的帮助屏幕:
BusyBox v1.15.3 (2018-08-13 13:52:22 NOVT) multi-call binary
Usage: sed [-efinr] SED_CMD [FILE]...
Options:
-e CMD Add CMD to sed commands to be executed
-f FILE Add FILE contents to sed commands to be executed
-i Edit files in-place
-n Suppress automatic printing of pattern space
-r Use extended regex syntax
If no -e or -f is given, the first non-option argument is taken as the sed
command to interpret. All remaining arguments are names of input files; if no
input files are specified, then the standard input is read. Source files
will not be modified unless -i option is given.
我的问题是:如何使用 sed 命令从文件中提取值?
答案1
如果您知道只有一行会匹配,正确的方法是
sed -n 's/ *tcpportmin: \([[:digit:]]*\).*/\1/p' cfg.yaml
该-n
标志抑制所有输出,但由显式 sed 命令触发的输出除外,例如p
.因此,上面的 sed 仅输出进行替换的行。
您可以将输出保存在变量中
TCP_PORT_MIN=$(sed -n 's/ *tcpportmin: \([[:digit:]]*\).*/\1/p' cfg.yaml)
请注意,为了可读性和嵌套,您应该使用$()
反引号而不是反引号。