使用 sed 和正则表达式从文件中提取数据

使用 sed 和正则表达式从文件中提取数据

我有一个在带有 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)

请注意,为了可读性和嵌套,您应该使用$()反引号而不是反引号。

相关内容