-1

私はいつも使っている簡単なテキスト処理スクリプトをいくつか持っており、これらのスクリプトを Ruby に翻訳して言語に慣れたいと思っています。

これは、実行できない最初のスクリプトです。

#!/usr/bin/env ruby

@text = ARGF.read

@replacements = [{:from=>"—", :to=>". "}, {:from=>"ffl", :to=>"ffl"}, {:from=>"ffi", :to=>"ffi"}, {:from=>"fi", :to=>"fi"}, {:from=>"fl", :to=>"fl"}, {:from=>"ff", :to=>"ff"}, {:from=>"æ", :to=>"ae"}, {:from=>"é", :to=>"e"}, {:from=>"Ç", :to=>"s"}, {:from=>"ü", :to=>"u"}, {:from=>"â", :to=>"a"}, {:from=>"ä", :to=>"a"}, {:from=>"à", :to=>"a"}, {:from=>"å", :to=>"a"}, {:from=>"ç", :to=>"s"}, {:from=>"ê", :to=>"e"}, {:from=>"ë", :to=>"e"}, {:from=>"è", :to=>"e"}, {:from=>"ï", :to=>"i"}, {:from=>"î", :to=>"i"}, {:from=>"ì", :to=>"i"}, {:from=>"Ä", :to=>"a"}, {:from=>"Å", :to=>"a"}, {:from=>"É", :to=>"e"}, {:from=>"ô", :to=>"oh"}, {:from=>"ö", :to=>"oe"}, {:from=>"ò", :to=>"o"}, {:from=>"û", :to=>"uu"}, {:from=>"ù", :to=>"u"}, {:from=>"ÿ", :to=>"o"}, {:from=>"Ö", :to=>"o"}, {:from=>"Ü", :to=>"u"}, {:from=>"á", :to=>"ah"}, {:from=>"í", :to=>"ee"}, {:from=>"ó", :to=>"oh"}, {:from=>"ú", :to=>"uu"}, {:from=>"ñ", :to=>"ny"}, {:from=>"Ñ", :to=>"ny"}] 

@replacements.each do |pair|
  @text.gsub!(/#{pair[:from]}/, pair[:to])
end

puts @text

そして、ここに私が得るエラーがあります:

/home/alec/.bei/under-boac:5: invalid multibyte char (US-ASCII)
/home/alec/.bei/under-boac:5: invalid multibyte char (US-ASCII)
/home/alec/.bei/under-boac:5: syntax error, unexpected $end, expecting '}'
@replacements = [{:from=>"—", :to=>". "}, {:from=>"ffl"...
                            ^

その一部は、「 Ruby での STDIN のベスト プラクティスは? 」に基づいています。

4

4 に答える 4

4

これは、読みやすいように再フォーマットされた基本コードです。

@replacements = [
  { :from => "—", :to => ". "  },
  { :from => "ffl", :to => "ffl" },
  { :from => "ffi", :to => "ffi" },
  { :from => "fi", :to => "fi"  },
  { :from => "fl", :to => "fl"  },
  { :from => "ff", :to => "ff"  },
  { :from => "æ", :to => "ae"  },
  { :from => "é", :to => "e"   },
  { :from => "Ç", :to => "s"   },
  { :from => "ü", :to => "u"   },
  { :from => "â", :to => "a"   },
  { :from => "ä", :to => "a"   },
  { :from => "à", :to => "a"   },
  { :from => "å", :to => "a"   },
  { :from => "ç", :to => "s"   },
  { :from => "ê", :to => "e"   },
  { :from => "ë", :to => "e"   },
  { :from => "è", :to => "e"   },
  { :from => "ï", :to => "i"   },
  { :from => "î", :to => "i"   },
  { :from => "ì", :to => "i"   },
  { :from => "Ä", :to => "a"   },
  { :from => "Å", :to => "a"   },
  { :from => "É", :to => "e"   },
  { :from => "ô", :to => "oh"  },
  { :from => "ö", :to => "oe"  },
  { :from => "ò", :to => "o"   },
  { :from => "û", :to => "uu"  },
  { :from => "ù", :to => "u"   },
  { :from => "ÿ", :to => "o"   },
  { :from => "Ö", :to => "o"   },
  { :from => "Ü", :to => "u"   },
  { :from => "á", :to => "ah"  },
  { :from => "í", :to => "ee"  },
  { :from => "ó", :to => "oh"  },
  { :from => "ú", :to => "uu"  },
  { :from => "ñ", :to => "ny"  },
  { :from => "Ñ", :to => "ny"  }
] 

@replacements.each do |pair|
  @text.gsub!( /#{ pair[:from] }/, pair[:to] )
end

これは単純化でき、ハッシュを組み合わせて 1 つの大きなものにし、ちなみに、ハッシュとして使用する必要があります。

# encoding: utf-8

@replacements = {
  "—" => ". "  ,
  "ffl" => "ffl" ,
  "ffi" => "ffi" ,
  "fi" => "fi"  ,
  "fl" => "fl"  ,
  "ff" => "ff"  ,
  "æ" => "ae"  ,
  "é" => "e"   ,
  "Ç" => "s"   ,
  "ü" => "u"   ,
  "â" => "a"   ,
  "ä" => "a"   ,
  "à" => "a"   ,
  "å" => "a"   ,
  "ç" => "s"   ,
  "ê" => "e"   ,
  "ë" => "e"   ,
  "è" => "e"   ,
  "ï" => "i"   ,
  "î" => "i"   ,
  "ì" => "i"   ,
  "Ä" => "a"   ,
  "Å" => "a"   ,
  "É" => "e"   ,
  "ô" => "oh"  ,
  "ö" => "oe"  ,
  "ò" => "o"   ,
  "û" => "uu"  ,
  "ù" => "u"   ,
  "ÿ" => "o"   ,
  "Ö" => "o"   ,
  "Ü" => "u"   ,
  "á" => "ah"  ,
  "í" => "ee"  ,
  "ó" => "oh"  ,
  "ú" => "uu"  ,
  "ñ" => "ny"  ,
  "Ñ" => "ny"  
}
@replacements.each do |k,v|
  @text.gsub!(k, v)
end

注: 「エンコード コメント」を使用して、Ruby が文字のエンコードを理解できるようにします。

しかし、同じハッシュを使用すると、そのループを次のように減らすことができ、非常に高速に実行されます。

@text.gsub!(Regexp.union(@replacements.keys), @replacements)
于 2013-01-09T20:34:55.810 に答える
2

ソース ファイルで非 7 ビット ASCII を使用している場合は、使用されている文字セットを識別するためにヘッダーを追加する必要があります。例:

#!/usr/bin/env ruby
# encoding: utf-8

さらに、ここでは非常に非効率的なことを行っており、適切な正規表現を構築する場合、O(1) でこれを行うことができる場合、ファイルに O(N) パスを必要とします。

replace_map = Hash[@replacements.collect { |r| [ r[:from], r[:to] ] }]
replace_regex = Regexp.new("(#{replace_map.keys.collect { |r| Regexp.escape(r) }.join('|')})")

@text.gsub!(replace_regexp) do |s|
  replace_map[s[1]]
end

:fromそこにある奇妙な/:toペアリングの代わりに、キー/値マッピングを使用する方がはるかに簡単です。

于 2013-01-09T20:17:13.460 に答える
2
#encoding: utf-8

@text = "öbñ"
@replacements = [{:from=>"—", :to=>". "}, {:from=>"ffl", :to=>"ffl"}, {:from=>"ffi", :to=>"ffi"}, {:from=>"fi", :to=>"fi"}, {:from=>"fl", :to=>"fl"}, {:from=>"ff", :to=>"ff"}, {:from=>"æ", :to=>"ae"}, {:from=>"é", :to=>"e"}, {:from=>"Ç", :to=>"s"}, {:from=>"ü", :to=>"u"}, {:from=>"â", :to=>"a"}, {:from=>"ä", :to=>"a"}, {:from=>"à", :to=>"a"}, {:from=>"å", :to=>"a"}, {:from=>"ç", :to=>"s"}, {:from=>"ê", :to=>"e"}, {:from=>"ë", :to=>"e"}, {:from=>"è", :to=>"e"}, {:from=>"ï", :to=>"i"}, {:from=>"î", :to=>"i"}, {:from=>"ì", :to=>"i"}, {:from=>"Ä", :to=>"a"}, {:from=>"Å", :to=>"a"}, {:from=>"É", :to=>"e"}, {:from=>"ô", :to=>"oh"}, {:from=>"ö", :to=>"oe"}, {:from=>"ò", :to=>"o"}, {:from=>"û", :to=>"uu"}, {:from=>"ù", :to=>"u"}, {:from=>"ÿ", :to=>"o"}, {:from=>"Ö", :to=>"o"}, {:from=>"Ü", :to=>"u"}, {:from=>"á", :to=>"ah"}, {:from=>"í", :to=>"ee"}, {:from=>"ó", :to=>"oh"}, {:from=>"ú", :to=>"uu"}, {:from=>"ñ", :to=>"ny"}, {:from=>"Ñ", :to=>"ny"}] 

# Hammer the @replacements into one Hash like {"—"=>". ", "ffl"=>"ffl"}:
from_to = Hash[@replacements.map{|h| h.values}]
# Generate one Regular expression to catch all keys:
re = Regexp.union(from_to.keys)
# Let gsub do the work in one pass:
@text.gsub!(re, from_to)

これは、@tadman のコードとほぼ同じです。#encoding: utf-8問題を解決する必要があります。残りの行は、テキストを 38 回スキャンすることを防ぎます。

于 2013-01-09T20:26:55.703 に答える
0

単純化することもできます:

@replacements=Hash[*%w[— .  ffl ffl ffi ffi fi fi fl fl ff ff æ ae é e Ç s ü u â a ä a à a å a ç s ê e ë e è e ï i î i ì i Ä a Å a É e ô oh ö oe ò o û uu ù u ÿ o Ö o Ü u á ah í ee ó oh ú uu ñ ny Ñ ny]]
于 2014-07-09T16:24:15.167 に答える