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

1行に複数の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

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)

$()読みやすくするために、バックティックの代わりにバックティックを使用する必要があります。

おすすめ記事