特定の文字列が浮動小数点であるかどうかを確認するには?これは浮動小数点で可能です。
12.245
+.0009
3.11e33
43.1E11
2e-14
私が試したことは次のとおりです。
grep "^[+\-\.0-9]"
grep "^[+-]*[0-9]"
grep "^[+\-\.0-9]"
他の多くの関連がありますが、まったくフィルタリングされません。ほぼすべての文字列が交差します。この問題をどのように解決できますか?
答え1
grep -xE '[-+]?[0123456789]*\.?[0123456789]+([eE][-+]?[0123456789]+)?'
を使用して-x
行の先頭と位置に正規表現を固定するので、行のどこにもパターンが見つからず、行がパターン全体と一致する必要があります。
サポートされているすべての項目を一致させるにはPOSIX/Cstrtod()
このユーティリティの多くの実装で認識されるように、次のようprintf
になります。
r=[$(locale decimal_point)]
d=[0123456789]
h=[0123456789abcdefABCDEF]
grep -xE "[[:space:]]*[-+]?($d*$r?$d+([eE][-+]?$d+)?|\
0[xX]$h*$r?$h*([pP][-+]?$d+)?|\
[iI][nN][fF]([iI][nN][iI][tT][yY])?|\
[nN][aA][nN]|\
NAN\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]+\))"
0x3f、0xFP-4、-Infinity、NAN(何でも)のようなものも同様です。
$ printf '%g\n' 0x3f 0xFp-4 -Infinity 'NAN(whatever)'
63
0.9375
-inf
nan
答え2
選ぶPythonソリューション(ドラゴン少ない複雑な入力):
サンプルinput.txt
ファイル:
11
12.245
+.0009
---0
3.11e33
43.1E11
2e-14
t12
aaa
10.001
check_float.py
スクリプト:
import sys
with open(sys.argv[1], 'r') as inp:
f = 'No'
for l in inp.read().splitlines():
try:
if float(l) and '.' in l: f = 'Yes'
except ValueError:
f = 'No'
finally:
print '{0} - {1}'.format(l, f)
使用法:
python check_float.py input.txt
出力:
11 - No
12.245 - Yes
+.0009 - Yes
---0 - No
3.11e33 - Yes
43.1E11 - Yes
2e-14 - Yes
t12 - No
aaa - No
10.001 - Yes
答え3
免責事項:これは不完全な解決策です。 PerlのScalar::Util::looks_like_number()
機能は、これを行うための最良のルーチン選択ではないかもしれません。バラよりStéphane Chazelasは以下についてコメントしました。。
誰かがそれを見て何かを選びたいならcoproc
ここに残しておきます。
できるだけ多くの浮動小数点型と一致するように独自の正規表現を作成するのではなく、すでに実装されているライブラリを使用してください。
perl -MScalar::Util -ne 'exit !Scalar::Util::looks_like_number($_)'
bash
シェル関数として:
is_number () {
perl -MScalar::Util -ne 'exit !Scalar::Util::looks_like_number($_)' <<<"$1"
}
is_number hello && echo 'hello is a number'
is_number 1.234 && echo '1.234 is a number'
bash
共同プロセスへ(数値をテストするたびにPerlプロセスを開始しないため):
coproc PERLIO=:raw perl -MScalar::Util -ne \
'print Scalar::Util::looks_like_number($_) ? "Yes" : "No", "\n"'
while IFS= read -r -p 'Number please: ' possnum; do
printf '%s\n' "$possnum" >&${COPROC[1]}
read -u ${COPROC[0]}
case "$REPLY" in
Yes) printf '%s is a number\n' "$possnum" ;;
No) printf '%s is _not_ a number\n' "$possnum" ;;
esac
done
kill "$COPROC_PID"
または2つを組み合わせます。
coproc PERLIO=:raw perl -MScalar::Util -ne \
'print Scalar::Util::looks_like_number($_) ? "Yes" : "No", "\n"'
is_number () {
printf '%s\n' "$1" >&${COPROC[1]}
local REPLY
read -u ${COPROC[0]}
[ "$REPLY" = 'Yes' ] && return 0
return 1
}
while IFS= read -r -p 'Number please: ' possnum; do
if is_number "$possnum"; then
printf '%s is a number\n' "$possnum"
else
printf '%s is a _not_ a number\n' "$possnum"
fi
done
kill "$COPROC_PID"