#概要
docgrep.rbをpythonに移植してWord文書をgrepするツール(docgrep.py)を作ります。
参考:
実用上はWord/Excel/PDFをgrepできる「SearchApp」というGUIツールのほうがいいかもしれません。
次回は、ページ数を表示するようにdocgrep.pyを改造します。
※行数も表示してみようかと思いますが、Wordの行(Sentence)はテキストエディタと違って句点[。]やピリオド[ . ]で区切られる概念なのでイメージと合わない気もする?
ExcelGrepとdocgrep.rb-日本語を活かした情報処處理入門
先づ、docgrep.rb、Rubyで書かれたワード用のgrepコマンドである。勿論、正規表現が使へる。ただし、このコマンドはファイル名は表示しても、頁數や行數は表示してくれない。
#使い方
python docgrep.py [-o] <expr> files...
引数 | 省略可否 | 3 |
---|---|---|
-o |
省略可能 | ヒットしたWord文書を表示する。省略した場合はprint出力。 |
<expr> |
必須 | 検索文字列(正規表現) |
files... |
必須 | ファイル名(複数可) |
###注
単純移植したらワイルドカード展開が使えなくなっていました。
コマンドライン引数のワイルドカードを展開する-blog.PanicBlanket.com
Ruby はコマンドラインのワイルドカードを展開してくれる。
・・・
でも、Python はそんな気の利いたことしてくれない。
そこで、glob モジュールの出番になる。
⇒次回で解決
#コード
# -*- coding: utf-8 -*-
import argparse
import win32com.client
import re
import pathlib
def docgrep(expr="", files=[], args_o=False):
pattern = re.compile(expr)
wd=win32com.client.DispatchEx("Word.Application")
quit =True
for doc in files:
doc = str(pathlib.Path(doc).resolve())
print(f"file: {doc}")
found = False
wdoc = wd.Documents.Open(FileName=doc, ConfirmConversions=None, ReadOnly=True)
for sentence in wdoc.Sentences:
txt = sentence.Text
m = pattern.search(txt)
if m:
found = True
quit = False
if not args_o:
print(txt)
else:
sentence.Select()
break
if not found or not args_o:
wdoc.Close(SaveChanges=0)
if quit or not args_o:
wd.Quit()
else:
wd.Visible = True
if __name__ == "__main__":
parser = argparse.ArgumentParser(usage="%(prog)s [-o] <expr> files...")
parser.add_argument("-o", action="store_true")
parser.add_argument("expr", type=str)
parser.add_argument("files", type=str, nargs="*")
args = parser.parse_args()
docgrep(expr=args.expr, files=args.files, args_o=args.o)
#docgrep.rbについて
「Rubyを256倍使うための本 邪道編, arton(著)」のWordをgrepするRubyスクリプトです。
サンプルプログラムがwebarchiveから取得できます。
- オブジェクト指向スクリプト言語Rubyを256倍使うための本のためのホームページ@webarchive
資料室
Rubyを256倍使うための本 邪道編のサンプルプログラム 著者、artonさんのホームページはこちら
ruby 2.2.1で動作させたときのパッチを置いときます。
##docgrep.rbのパッチ
- getopts → optparseに変更
- GetAbsolutePathNameで絶対パスに変換
- usageの文字列を修正(書籍に合わせた)
--- C:/tmp/docgrep.rb Sun Jun 24 20:32:09 2018
+++ C:/tmp/docgrep_new.rb Tue Jun 26 01:20:14 2018
@@ -1,11 +1,14 @@
require "win32ole" #(A)
-require "getopts"
+require "optparse"
def usage
- print "usage: ruby docgrep.rb [-[o]] <expr> files...\n"
+ print "usage: ruby docgrep.rb [-o] <expr> files...\n"
end
-unless getopts("o")
+
+begin
+ args = ARGV.getopts('o')
+rescue OptionParser::InvalidOption
usage
exit(1)
end
@@ -17,10 +20,12 @@
pattern = Regexp.new(ARGV.shift, Regexp::IGNORECASE)
wd = WIN32OLE.new("Word.Application") #(B)
+fso = WIN32OLE.new("Scripting.FileSystemObject")
quit = true
for doc in ARGV
begin
+ doc = fso.GetAbsolutePathName(doc)
print "file: " + doc + "\n"
found = false
wdoc = wd.Documents.open doc #(C)
@@ -30,7 +35,7 @@
if $&.nil? == false
found = true
quit = false
- if $OPT_o.nil?
+ if !args["o"]
print txt + "\n"
else
sentence.select #(F)
@@ -38,13 +43,13 @@
end
end
end
- if found == false || $OPT_o.nil?
+ if found == false || !args["o"]
wdoc.close #(G)
end
end
end
-if quit || $OPT_o.nil?
+if quit || !args["o"]
wd.Quit #(H)
else
wd.visible = true #(I)
##GetAbsolutePathNameで絶対パスに変換
Rubyを256倍使う本 邪道編の間違い探しや訂正などなど - COM Meets Ruby
(略) 相対パスで引数を記述するとNTや2000だとdocgrep.rbはちゃんと動かない。だから、51ページのリストの#Cの部分を
wdoc = wd.Documents.open File.expand_path(doc)
としてください。ここからわかること。MSもパスの区切りに''を使うのが必ずしも良いと思ってるわけじゃなさそうだということ。Wordは'/'でもちゃんと処理する。
File.expand_path(doc)
を使ったところ、ファイル名/フォルダ名のスペースが**%20
**でWordに渡ってしまい、これが処理できなさそうです。
FileSystemObjectのGetAbsolutePathNameを使うといいようにやってくれます。
#関連
Python(pywin32)でWordを操作する[1] - Wordオブジェクトモデル
Python(pywin32)でWordを操作する[2] - Wordを起動/終了する
Python(pywin32)でWordを操作する[3] - 新規ドキュメント作成
Python(pywin32)でWordを操作する[4] - 文字列を入力/取得/削除する
Python(pywin32)でWordを操作する[5] - ドキュメントをファイルに保存する、Wordのオプション変更
Python(pywin32)でWordを操作する[6] - 特定のタイトルが付いているウィンドウの操作
Python(pywin32)でWordを操作する[7] - 既存文書を開く/閉じる(Documents.Open(), Document.Close())
Python(pywin32)でWordを操作する[8] - 段落単位の文字列取得, 統計(ページ数, 段落数,etc)取得
Python(pywin32)でWordを操作する[9] - Word文書をgrepする(docgrep.rb移植)
Python(pywin32)でWordを操作する[10] - Word文書をgrepする(ページ数表示, 行数表示, ワイルドカード展開)
#参考