文字列内の位置で数字を一致させようとしています。たとえば、文字列"1234567"
で、2 番目から 4 番目の文字を選択したいと思います: "234"
. "D9873Y.31"
も上がるはず"987"
です。何か提案はありますか?
3 に答える
正規表現は必要ありません。次を使用できますString#[]
。
s = '1234567'
s[1..3] #=> "234"
s = 'D9873Y.31'
s[1..3] #=> "987"
これには正規表現を使用できます。パターンは柔軟性があり、いくつかの異なる方法で記述できます。不可解な性質のためにメンテナンスの悪夢になる可能性があるため、私はそれらを非常にシンプルに保つようにしています:
"1234567"[/^.(.{3})/, 1]
=> "234"
"D9873Y.31"[/^.(.{3})/, 1]
=> "987"
"1234567".match(/^.(.{3})/)[1]
=> "234"
"D9873Y.31".match(/^.(.{3})/)[1]
=> "987"
named-capturesを利用することもできます:
/^.(?<chars2_4>.{3})/ =~ "1234567"
chars2_4
=> "234"
/^.(?<chars2_4>.{3})/ =~ "D9873Y.31"
chars2_4
=> "987"
それはすべて素晴らしいことですが、それらを掘り下げてよく学ぶことが本当に重要です。なぜなら、間違ったやり方をすると、間違ったデータを取得したり、さらに悪いことに、単純なことをするために正規表現エンジンを非常に難しくしてスクリプトを遅くしたりする可能性があるからです。
たとえば、^
上記を使用しました。^
は、文字列の先頭である行頭と、改行の直後の文字に一致します。短い文字列の場合は問題ありませんが、特に改行が埋め込まれた長い文字列は、エンジンの速度を低下させる可能性があります。代わりに、 を使用することをお勧めします\A
。$
または\Z
またはを使用する場合も同じ状況が適用され\z
ます。これは、「アンカー」の正規表現ドキュメント セクションからのものです。
^
- 行頭に一致$
- 行末に一致\A
- 文字列の先頭に一致します。\Z
- 文字列の末尾に一致します。文字列が改行で終わる場合、改行の直前に一致します\z
- 文字列の末尾に一致
そのため、正規表現の使用を避け、代わりに @AndrewMarshall が推奨するような部分文字列を使用したい場合があります。
単純な部分文字列の方法が望ましい別の理由は次のとおりです。
require 'benchmark'
N = 1_000_000
Benchmark.bm(13) do |b|
b.report('string index') { N.times {
"1234567"[1..3]
"D9873Y.31"[1..3]
} }
b.report('regex index') { N.times {
"1234567"[/^.(.{3})/, 1]
"D9873Y.31"[/^.(.{3})/, 1]
} }
b.report('match') { N.times {
"1234567".match(/^.(.{3})/)[1]
"D9873Y.31".match(/^.(.{3})/)[1]
} }
b.report('named capture') { N.times {
/^.(?<chars2_4>.{3})/ =~ "1234567"
/^.(?<chars2_4>.{3})/ =~ "D9873Y.31"
} }
b.report('look behind') { N.times {
"1234567"[/(?<=^.{2}).{3}/, 1]
"D9873Y.31"[/(?<=^.{2}).{3}/, 1]
} }
end
どちらが返されますか:
user system total real
string index 0.730000 0.000000 0.730000 ( 0.727323)
regex index 1.370000 0.000000 1.370000 ( 1.377121)
match 4.400000 0.000000 4.400000 ( 4.398849)
named capture 5.240000 0.010000 5.250000 ( 5.243799)
look behind 1.430000 0.000000 1.430000 ( 1.437286)
アンカーを使用した後読みを使用してそれを行うことができます。例:
(?<=^.{2}).{3}
あなたに345を与えます