파이썬 (pywin32)에서 Word 작업하기 [9] - Word 문서 grep (docgrep.rb 이식)

개요



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는 커맨드 라인 와일드 카드를 확장합니다.
···
하지만 파이썬은 그런 느낌을주지 않습니다.
그래서 glob 모듈의 차례가 된다.

다음 번 에서 해결

코드



docgrep.py
# -*- 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에서 얻을 수 있습니다.

  • 객체지향 스크립트 언어 루비를 256배 사용하는 책을 위한 홈페이지 @ webarchive

  • 자료실
    Ruby를 256배 사용하기 위한 책 사도편의 샘플 프로그램 저자, arton씨의 홈페이지는 이쪽

    ruby 2.2.1에서 실행할 때 패치을 놓습니다.

    docgrep.rb 패치


  • getopts → optparse로 변경
  • GetAbsolutePathName으로 절대 경로로 변환
  • usage 문자열 수정 (책에 맞게)

  • diff.patch
    --- 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이라고 dogrep.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] - 문자열 입력/취득/삭제
    파이썬 (pywin32)에서 Word 작업하기 [5] - 문서를 파일에 저장, Word 옵션 변경
    Python(pywin32)에서 Word 작업하기 [6] - 특정 제목이 있는 창 작업
    Python(pywin32)에서 Word 작업 [7] - 기존 문서 열기/닫기(Documents.Open(), Document.Close())
    Python(pywin32)에서 Word 조작하기 [8] - 단락 단위의 문자열 취득, 통계 (페이지 수, 단락 수, etc) 취득
    파이썬 (pywin32)에서 Word 작업하기 [9] - Word 문서 grep (docgrep.rb 이식)
    Python(pywin32)에서 Word 작업하기 [10] - Word 문서 grep(페이지 수 표시, 행 수 표시, 와일드카드 확장)

    참고


  • Ruby를 256배 사용하기 위한 책 사도편
  • Ruby를 256배 사용하는 책 사도편의 실수 찾기나 정정 등 등 - COM Meets Ruby

  • 객체지향 스크립트 언어 루비를 256배 사용하는 책을 위한 홈페이지 (webarchive)
  • SearchApp - Vector
  • FileSystemObject 개체-msdn
  • 명령줄 인수 와일드카드 확장 -blog.PanicBlanket.com
  • ExcelGrep과 docgrep.rb - 일본어를 살린 정보 처학 입문
  • 좋은 웹페이지 즐겨찾기