2009-08-17 6 views
9

背景:私は他のページへの参照を含む文字列を持っています。ページは "#12"の形式でリンクされています。ハッシュの後にページのIDが続きます。Ruby、gsub、regex

は、私は次の文字列を持っていると言う:

str = 'This string links to the pages #12 and #125' 

私はすでにリンク必要なページのIDを知っている:

page_ids = str.scan(/#(\d*)/).flatten 
=> [12, 125] 

どのページIDによるIループすることができますし、#をリンク12と#125をそれぞれのページに追加しますか?私は(レールに)以下ならば、私はに実行した問題は次のとおりです。

page_ids.each do |id| 
    str = str.gsub(/##{id}/, link_to("##{id}", page_path(id)) 
end 

これは、#12のために正常に動作しますが、それは12のIDとページに#125の「12」の部分をリンクします。

ご協力いただければ幸いです。あなたのインデックスは常にワード境界で終了した場合

答えて

12

、あなたはそれを一致させることができます:

page_ids.each do |id| 
    str = str.gsub(/##{id}\b/, link_to("##{id}", page_path(id)) 
end 

は、あなただけの検索パターンに単語境界記号\bを追加する必要があり、それは置換パターンのために必要ではありません。

+0

マーベラスを使用することができます。私は\ bについて知りませんでした。あなた、救命救助者です。 –

21

代わりに最初のIDを抽出し、それらを置き換えるので、あなたは、単に見つけることができると一度にそれらを交換する:あなたはどこかのIDを必要とするので、あなたが抽出工程を省略することができない場合であっても

str = str.gsub(/#(\d*)/) { link_to("##{$1}", page_path($1)) } 

をそれ以外の場合は、各IDの文字列全体を調べる必要がないため、これははるかに高速になるはずです。

PS:strが他のどこからも参照されていない場合、あなたはstr.gsub!代わりのstr = str.gsub

+2

これは正しい解決策です。 – Magnar

+1

これは効率的ですが、テキストの内容によっては偽陽性を生成する可能性があります。彼が参照する125ページがあり、ページのテキストに#112325のような文字列(注文番号など)があると想像してください。これは、それぞれの偽陽性の場合には死んだページへのリンクを生成します。ページと単語の境界線のリストを使用して検索することは簡単ではありませんが、その優雅さにもかかわらず、このソリューションよりも堅牢です。 – Pinochle

+2

#112325のような文字列があれば、それはpage_ids配列内にあるので、どちらの方法でもデッドリンクが生成されます。私のgsubはOPのスキャンと同じ正規表現を使用することに注意してください。彼らは正確に同じIDを見つけるでしょう。 – sepp2k