Sed

使用 sed 和正則表達式從文件中提取數據

  • May 28, 2020

我有一個使用 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 命令從文件中提取值?

如果您知道只有一行匹配,那麼正確的方法是

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)

$()請注意,為了可讀性和嵌套,您應該使用反引號而不是反引號。

引用自:https://unix.stackexchange.com/questions/589582