問題
私はそれが何をしているかを示すために(フリースペースモードでの)コメントをあなたの正規表現を定義します。 '|'
は、文字クラス内の特殊文字(「や」)ではないことを
r =
/
( # begin capture group 1
\A # match beginning of string (or does it?)
| # or
[ \u00A0|\r|\n|\v|\f] # match one of the characters in the string " \u00A0|\r\n\v\f"
) # end capture group 1
(\d?\d) # match one or two digits in capture group 2
[ \u00A0|\r|\n|\v|\f] # match one of the characters in the string " \u00A0|\r\n\v\f"
: # match ":"
( # begin capture group 3
\d # match a digit
| # or
[ \u00A0|\r|\n|\v|\f] # match one of the characters in the string " \u00A0|\r\n\v\f"
| # or
\z # match the end of the string
) # end capture group 3
/x # free-spacing regex definition mode
注意。それは普通のキャラクターとして扱われます。 ('|'
は次のように「または」文字クラスを一致させるために、その中に任意の1つの文字を強制するために使用されているので、何の目的を果たしていないだろう文字クラス内で処理した場合であっても。)
その後
line = " 0 : 28 : 37.02"
を仮定それは文字ではなく、(それは例外を発生させない理由、私は知りませんが)文字だけが一致していないため、キャプチャグループ1ライン(\A
)の初めに
line.gsub(r, '\2:\3')
#=> " 0: 28 : 37.02"
$1 #=> " "
$2 #=> "0"
$3 #=> " "
が一致しません。 "or"('|'
)の特殊文字は、正規表現エンジンが文字列" \u00A0|\r\n\v\f"
の1文字に一致させようとします。したがって、文字列line
の先頭にある3つの空白のいずれかに一致します。
次のキャプチャグループ2は、"0"
をキャプチャします。それを行うには、捕捉グループ1は、インデックス2のスペースを捕捉していなければならない。line
。次にもう1つのスペースとコロンがマッチし、最後にキャプチャグループ3がコロンの後のスペースを取ります。
したがって、部分文字列' 0 : '
は'\2:\3' #=> '0: '
に置き換えられるため、gsub
は" 0: 28 : 37.02"
を返します。 '0'
より前の1つのスペースが削除されています(ただし、保持されているはずです)。
ソリューション
ここでは、1つまたは2つの数字(ない以上)で先行している1つのまたは複数のUnicodeの空白文字の最後を削除することができる方法だとの末尾にコロンが続いています文字列またはコロンの後ろに空白または数字が続きます。 (やれやれ!)
def trim(str)
str.gsub(/\d+[[:space:]]+:(?![^[:space:]\d])/) do |s|
s[/\d+/].size > 2 ? s : s[0,s.size-2] << ':'
end
end
正規表現がで(否定先読み)が続いていない、(これらすべての文字が一致している)コロン、一つ以上の空白文字に続いて、「マッチ一つ以上の数字を読み込み、ユニコードの空白または数字以外の文字 "を含む。一致がある場合は、最初に何桁の数字があるかを確認します。 2つ以上の一致が返された場合(変更なし)、一致する文字がコロンの前の空白文字から削除され、修正された一致が返されます。
trim " 0 : 28 : 37.02"
#=> " 0: 28: 37.02" xxx
trim " 0\v: 28 :37.02"
#=> " 0: 28:37.02"
trim " 0\u00A0: 28\n:37.02"
#=> " 0: 28:37.02"
trim " 123 : 28 : 37.02"
#=> " 123 : 28: 37.02"
trim " A12 : 28 :37.02"
#=> " A12: 28:37.02"
trim " 0 : 28 :"
#=> " 0: 28:"
trim " 0 : 28 :A"
#=> " 0: 28 :A"
の例のように、文字列内の文字だけが数字、空白文字とコロンある、場合、後読みは必要ありません。
POSIX式[[:space:]]
の代わりに、構造体\p{Space}
を使用できます。両方とも、例に示されているものを含むUnicode空白文字のクラスに一致します。 3桁目を除く
少なくともテストのためには、 'gsub! 'の代わりに' gsub'を使用してください。後者は 'line'を変更するので、実行するとコードを変更して再度実行し、' line'を再初期化しないと犬の朝食が得られ、何が起こっているのか完全に困惑します。とにかくバングバージョンを使いたいのはなぜわかりません。 –