xgrep.rb

30分シリーズ、その14。XMLgrep、xgrep.rb。
TypingManiaの歌詞ダウンロードに使おうと思ったら、XMLがvalidじゃなかったので使えなかった可哀想な子。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<musicinformation>
<musicinfo id="0" xmlpath="XML/Memorability.xml"
                  musicpath="mp3/Memorability.mp3">
	<musicname>Memorability</musicname>
	<artist>緋火流</artist>
	<genre>Pop</genre>
	<level>04</level>
</musicinfo>
</musicinformation>

というのがXMLがあったとする。

すると、

$ xgrep musicinformation/musicinfo musiclist.xml
musiclist.xml: <musicinfo id="0" xmlpath="XML/Memorability.xml"
                  musicpath="mp3/Memorability.mp3">
	<musicname>Memorability</musicname>
	<artist>緋火流</artist>
	<genre>Pop</genre>
	<level>04</level>
</musicinfo>

$ xgrep musicname/text() musiclist.xml
musiclist.xml: Memorability

$ xgrep musicinfo/@id() musiclist.xml
musiclist.xml: 1

となります。

#!/opt/local/bin/ruby -w
require 'REXML/Document'

def xgrep(io,xpath,cmd,filename='<->',&print)
  include REXML
  doc = Document.new io
  
  doc.root.each_element(xpath){|elem|
    x = case cmd
        when /\Atext/
          elem.text
        when /\A@(\w+)/
          elem.attributes[$1]
        else
          elem
        end
    print.call "%s:\t%s" % [filename,x]
  }
end

if ARGV[0] =~ %r!(.*)/([^/]+)\(\)!
  xpath = $1
  cmd = $2
else
  xpath = ARGV[0]
  cmd = 'raw'
end
ARGV.shift

if ARGV.empty? then
  xgrep(STDIN,xpath,cmd,&method(:puts))
else
  ARGV.each do|filename|
    File.open(filename) do |io|
      xgrep(io,xpath,cmd,filename,&method(:puts))
    end
  end
end
  • grepを名乗るなら、行番号が欲しいところだ
  • XGrep