概要
シェルを使って数値データファイルの整形を行っている際,正規表現で詰まったのでメモ代わりに.
整数(1,2,3,...)と小数(1.1,2.5,...)と浮動小数点数(1.0E+10, 1.6e-19, ...)が入り混じったファイルから数値を抜き出す正規表現.
正規表現
以下の様な正規表現で抜き出せた.
[+-]?[0-9]+[\.]?[0-9]*[eE]?[+-]?[0-9]*
実際にはこれをgrep
なりegrep
なりに突っ込んで抜き出す.
コメントでいただいた指摘を受けた追記について
2016/8/30追記
@hikozaru_3 さんより,上の正規表現だと1+1
や5-2
のようなケースもマッチしてしまうという指摘がありました.
以下の正規表現が望ましいです.
[+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9]
また,これに併せてテスト用のスクリプトを修正したため,今まで記載していたセクションの下に修正後のものを追記します.
2017/6/22追記
@scivola さんより,1e+
のような「指数もどき」もマッチしてしまうという指摘がありました.
上のものよりも以下のもののほうが望ましいかと思われます.
[+-]?[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?
こちらの正規表現でのテスト結果ですが,現在多忙につき割愛(もしくは後日改めて追記)させていただきます...
2018/12/2追記
.123
のような小数点以下のみで数値を表現している場合は
[+-]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][+-]?[0-9]+)?
となるようです.
@Nabetani さんありがとうございます!!
テスト結果も編集しました.今あらためて見ると少し気持ち悪い結果もありますね。
以前のコード
例(正規表現にミスあり)
テスト用のスクリプト. egrep
の-o
オプションで条件に一致した部分だけを出力する.
#!/bin/bash
file=$1
for line in `cat ${file}`
do
echo ${line}
N=`echo ${line} | egrep -o '[+-]?[0-9]+[\.]?[0-9]*[eE]?[+-]?[0-9]*'`
echo "result = ${N}"
done
で、これにこんな感じのテストケースを放り込む
1
58
-5
2.8
-3.39
73.098abh
1.0e+29
1.6E-16
abc39
num=395479.27
で、実行結果
>./numtest.sh testfile.txt
1
result = 1
58
result = 58
-5
result = -5
2.8
result = 2.8
-3.39
result = -3.39
73.098abh
result = 73.098
1.0e+29
result = 1.0e+29
1.6E-16
result = 1.6E-16
abc39
result = 39
num=395479.27
result = 395479.27
正しく数値だけ抜き出せてると思う
例(2018/12/2修正版)
というわけで修正したシェルスクリプトです.
#!/bin/bash
file=$1
for line in `cat ${file}`
do
echo ${line}
N=`echo ${line} | egrep -o '[+-]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][+-]?[0-9]+)?'`
for res in $N
do
echo "result = ${res}"
done
done
これに併せてテストケースも増やしました.今回は1つの行に複数の数値があった場合も対応できるようにしています.
1
58
-5
2.8
-3.39
73.098abh
1.0e+29
1.6E-16
abc39
num=395479.27
1+1
234gh290
432-84
235hk23.4e-6
1e+
3e-
.123
.23h5
hoge
以下,結果.
1
result = 1
58
result = 58
-5
result = -5
2.8
result = 2.8
-3.39
result = -3.39
73.098abh
result = 73.098
1.0e+29
result = 1.0e+29
1.6E-16
result = 1.6E-16
abc39
result = 39
num=395479.27
result = 395479.27
1+1
result = 1
result = +1
234gh290
result = 234
result = 290
432-84
result = 432
result = -84
235hk23.4e-6
result = 235
result = 23.4e-6
1e+
result = 1
3e-
result = 3
.123
result = .123
.23h5
result = .23
result = 5
hoge
今あらためて結果を確認すると、.23h5
みたいなケースから.23
と5
が抜き出されるのは若干気持ち悪いですね...