
私はこれが非常に簡単な質問だと思い、Googleが質問の一部に多くの回答を見つけましたが、一緒に接続しようとするとうまくいかず、理由を理解できません。
シナリオは次のとおりです。
- テキストの多いファイルがあります。
- 行の1つが次のパターンと一致します。
foo = 1700;
- 抽出したい
1700
- 後でスクリプトで参照できるようにbashスクリプト変数に保存したいと思います。
3段階を超えられません。私が試したことは次のとおりです。
sed -nE 's/^foo = //p' file | sed -nE 's/;//p'
これは次のように印刷されます。
1700
大丈夫です。しかし、空白などを整える必要がある場合はどうすればいいですか?*
/が利用できない場合は+
どうすればいいのかわかりません。他の回答を使用*
/+
置き換えることができないことを理解しているので、これを行う方法がわかりません。 grepのマニュアルページを見ましたが、その用語を検索してもグループオプションは表示されません。私はawkでこの問題を解決する方法を知っていると思いますが、常に正規表現関数が少し不明瞭であり、コマンドラインスクリプトにエスケープが多すぎるため、理想的にはこれがこの問題を解決する唯一の方法ではありません。 。
答え1
まず、数値をキャプチャする方法を紹介します。
$ echo 'foo = 1700;' | sed -n -e 's/^foo = \([0-9]\+\).*/\1/p' 1700
これはデフォルト
sed
の基本 Regular Expressions (BRE) を使用します。 sed-E
オプションで拡張正規表現(ERE)を使用することもできます。echo 'foo = 1700;' | sed -n -E -e 's/^foo = ([0-9]+).*/\1/p' 1700
[0-9]+
括弧内のサブ式は(
...)
1つ以上の数字をキャプチャします。これは「キャプチャグループ」と呼ばれ、次に置き換えるために使用されます\1
。最初キャプチャグループ - キャプチャグループが複数ある場合は、\1、\2、\3などとして使用できます。この場合、sedスクリプトは行全体を\ 1キャプチャグループにのみ置き換えようとし、成功すると修正された行を印刷します。
sed
次に、出力を変数に入れたいです。あなたはこれでやるコマンドの置き換え。例えば$ myvar=$(echo 'foo = 1700;' | sed -n -E -e 's/^foo = ([0-9]+).*/\1/p') $ echo $myvar 1700
スクリプトで使用するには、ファイルをパイプするのではなく、sedの引数として使用します
echo ...
。myvar=$(sed -n -E -e 's/^foo = ([0-9]+).*/\1/p' file)
スペースをトリミングしたり、オプションの
=
先行スペースや周囲のオプションのスペースなどがある可能性がある行を処理します。myvar=$(sed -n -E -e 's/^[[:space:]]*foo[[:space:]]*=[[:space:]]*([0-9]+).*/\1/p' file)
sedの一部のバージョン(少なくともGNU sed、たぶん他のバージョン)はこれを理解している
perl's
\s
ので、次のように短縮できます。myvar=$(sed -n -E -e 's/^\s*foo\s*=\s*([0-9]+).*/\1/p' file)
答え2
完全性のためにおよびをサポートする正規表現の実装を使用して、次のgrep
ことを実行できます。-o
perl
-P
grep -Po 'foo\s*=\s*\K\d+'
どこ:
\s
空白文字と一致*
0個以上の先行原子。たとえば、\s*
ゼロ個以上の空白文字を一致させます。\d
10進数と一致します(通常は同じです[0123456789]
が、[0-9]
通常は文字は使用されません)。+
1つ以上の以前の原子と一致します。\K
一致する部分(コンテンツがeep、またはK
出力の場合)の開始をリセットします。grep -o
o
したがって、これは、指定された行に複数の数字が表示されても、1つ以上の数字と両方にfoo=
許可されている空白数のすべてのシーケンスを印刷します。=
を使用すると、一致する部分全体ではなく、指定されたキャプチャグループが一致するアイテムを印刷するために、後にpcregrep
数字を指定することもできます。-o
pcregrep -o1 'foo\s*=\s*(\d+)'
移植可能であれば、実際に実際を使用できますperl
。 ::
perl -lne 'print $1 for m{foo\s*=\s*(\d+)}g'
答え3
数値を選択するとしますfoo
。
echo 'foo = 1700;' | awk '$1=="foo" {print $NF+0}'
1700
デフォルトではawk
空白(単一の空白ではない)に分割されます。NF
はフィールド数です。この場合、3は$NF
3番目の空白フィールドの文字列値です。+0
この文字列を1700;
数値に変換します1700
。
同じ行では機能しますfoo = 1700;
が、同じ行では機能しませんfoo=1700;
。あなたの質問によると、余分な空白を削除することに興味があるのか、データに空白がなく、唯一の境界点が=
あるのかわかりません。;
存在するかどうかにかかわらず、スペースを無視するには、次を使用することをお勧めしますsed
。
echo 'foo=1700;' | sed -n 's/^foo *= *//p' | sed -e 's/;$//' -e 's/ *$//'
1700
答え4
awk '{for(i=1;i<=NF;i++){if($i ~ /foo/ && $0 ~ /foo.*=.*[0-9]*/){gsub(";","",$(i+2));print $(i+2)}}}' filename
テストを経てうまく機能しました