シェルスクリプトから部分文字列 "mode:" の後に数値を抽出する簡潔で読みやすい方法です。

シェルスクリプトから部分文字列

私はこの文字列を持っています:

DMT           mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive

パターン番号(最初:)の前の部分を抽出したいです。この場合は4です。予想どおり、パターン番号の長さは1桁または2桁にすることができ、その前のテキスト文字の長さがまったく同じであると信じることはできません。

動作する解決策があります。

$picked = "DMT           mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
echo $picked | awk -F"mode " '{print $2}' | tr : '\n' | head -n1

しかし、私はこれを行うよりエレガントな方法があるべきだと思います。エレガントで学習しやすく、後で読んでください(したがって、おそらく正規表現は含まれません)。私の夢のコマンドは次のとおりです。echo $picked | 「パターン」「:」の間

以下は、解析可能な入力範囲の必要性を示すいくつかの追加例です。

CEA           mode 7: 720x480 @ 60Hz 16:9, clock:27MHz x2 interlaced
CEA  (native)  mode 16: 1920x1080 @ 60Hz 16:9, clock:148MHz progressive
DMT           mode 58: 1680x1050 @ 60Hz 16:10, clock:146MHz progressive

ベストアンサー1

正規表現はより簡単な解決策です。いくつかのオプションは次のとおりです。

echo "$picked" | grep -oP '(?<=mode )\d+'
echo "$picked" | grep -oP '(?<=mode )[[:digit:]]+'

PCRE機能が気に入らない場合:

echo "$picked" | grep -oE 'mode [[:digit:]]+' | tr -d 'mode '

このtrコマンドは削除されません。言葉すべてを削除する「モード」数値「モデル」、「」。


本当に好きなら、「パターン」をクリックするまで単語を繰り返します。

echo "$picked" | awk '{for (i=1; i<NF; i++) if ($i == "mode") {print $(i+1); exit}}' | tr -d :

文字列はすでにシェル変数に含まれているので、bashパラメータの置き換えはどうですか?

tmp=${picked#*mode }    # remove up to "mode "
value=${tmp%%:*}        # remove the colon and everything after

それから

$ declare -p picked tmp value
declare -- picked="DMT           mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
declare -- tmp="4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
declare -- value="4"

引用する3.5.3 シェルパラメータの拡張マニュアルで(そしていくつかの詳細を簡単に説明):

  • ${var#pattern}削除する最短プレフィックスパターンマッチ
  • ${var##pattern}削除する最長プレフィックスパターンマッチ
  • ${var%pattern}削除する最短のサフィックスパターンマッチ
  • ${var%%pattern}削除する最長のサフィックスパターンマッチ

「最も短いもの」と「最も長いもの」の違いが重要です。与えられた文字列サフィックスには複数のコロンが含まれています。${tmp%:*}削除する場合にのみ使用してください。最後コロンとその後の文字です。

おすすめ記事