パスワードを忘れた? アカウント作成
226240 journal

Ryo.Fの日記: Pythonの良さが伝わってこない 9

日記 by Ryo.F

Pythonというか』で書いたとおり、Jythonを憶えることにしたので、まずは別件で依頼されたDNS(BIND)のゾーンデータを書き換えるスクリプトをPythonで書くことにした。
スクリプトは、一行ごとに読み込んで正規表現を使って、レコードを解釈しながら、対象レコードを見つけて書き換える、という感じだ。

結論。
Rubyより良いようには思えない。
Perlよりマシ…かなぁ。読みやすいとは思うけど。

誰かRyo.FにPythonを布教してください。Pythonで正規表現を使うと、

for line in sys.stdin:
  m = re.match('\s+(\d+)\s*;\s*serial',line)
  if m:
    print "SERIAL:", m.group(1)
    continue
  m = re.match('^(\S*)\s+',line)
  if m:
    print "NAME:", m.group(1)
    continue

みたいにしか書けんの?もっと簡潔にできんの?

この議論は、Ryo.F (3896)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
  • 何よりも、ソースを後で読めることが大事なのです。

    serial_pat = re.compile(r"""
            ^\s+ # leading spaces
            (?P\d+) # Serial Number
            \s*;\s*serial # trailing comment with SERIAL mark
    """, re.IGNORECASE | re.VERBOSE)

    for line in sys.stdin:
            m = serial_pat.search(line)
            if m:
                    print "SERIAL:", m.group('SERIAL')

    #いつもそう書いてる訳じゃないけどね。;-P

    ていうか、これって SOA を parse してるんじゃないよね。serial って書いてないところに serial があったらどうするの?

    • ソースを後で読めることが大事

      そうですか…。RubyがPythonより読みにくいとは思えないので、いまいち布教されきりません。
      ところで、コンパイラではないので、ソースと言うよりコードでしょうね。

      serial って書いてないところに serial があったらどうするの?

      どうもしません。スレーブサーバがマスタサーバからダウンロードしてきたゾーンファイルを書き換えるので、これでいいんです。人間が書くゾーンファイルを扱うなら、もう少しまじめに構文解析します。
      必要以上に労力を使うのは、趣味ならともかくですが、仕事ではやってはいけないことでしょう。
      といいながら、Pythonを新たに学習しようとする労力はどうなんだ、というツッコミは無粋です(笑)。

      親コメント
  • 「テキストファイルの各行をスキャンして、正規表現にマッチした行の部分文字列を抽出して表示する」だけのスクリプトをPythonで書くのは正直なところ「愚行」です。そういうものはAWKやPerlやRubyで書いた方が幸せになれます(俺はPerlもRubyも書けませんが)。

    Pythonで正規表現だの文字列だののモジュールを駆使してテキストファイルをいじっていると「これならAWKで書いた方が早かったじゃん」と思うことはよくありますね(苦笑)。

    もっとも、しょっぱなにAWKで書いたスクリプトを拡張してちょっと込み入ったことやらせようと考えると、途端にPythonに移行したくなるわけですけど。

    • 表示する」だけ

      じゃないんですけどね。実際には、書き換えルールを別のファイルから読み込んで、それに従って書き換えるんですけど、そこまで細かく書くと守秘義務ってもんが(笑)。

      「愚行」です。

      そうですか。てぇと、どういうものなら「愚行」ではないんでしょう?
      読みやすさからくる保守性の高さを利用して、大規模なアプリケーションを書く場合にいいとか?うーん…

      親コメント
      • 横からで恐縮ですが…

        Python使いには、正規表現は便利だけど多用しすぎると可読性やら保守性が悪くなると思っている人が多く、elderwand氏が「冗長な正規表現」を挙げているのもそういった理由からでしょう。

        私なら、正規表現使わずに書いちゃいますね。単に正規表現に慣れてないからですが。

        for line in sys.stdin:
          ls = line.split()
          if len(ls) == 0:
            continue
          try:
            i = ls.index('serial')
            print 'SERIAL:', ls[i-2]
          except ValueError:
            print 'NAME:', ls[0]

        --
        1を聞いて0を知れ!
        親コメント
        • 正規表現は便利だけど多用しすぎると可読性やら保守性が悪くなる

          なるほど確かに。
          しかし、

            try:
              i = ls.index('serial')
              print 'SERIAL:', ls[i-2]
            except ValueError:
              print 'NAME:', ls[0]

          この部分が可読性・保守性に優れているかと言うと…。やっぱり正規表現よりはマシか。

          でも、これよりもう少し複雑な例だと、どっちが複雑か解らないってことになりませんかね?例えば、私の出した例だと、「serial」は、コメントの中に書いてあることになってるわけですが、そうなると、

              i = ls.index('serial')
              j = ls.index(';')
              if i <> j + 1:
                raise ValueError
              print 'SERIAL:', ls[i-2]

          と、どっちの可読性が上か疑問になってきます。もっと巧い書き方はありそうですが。

          親コメント
          • 私がろくなコード書かないってのもありますが、確かに正規表現の方が可読性・保守性の高いコードになる可能性も十分にありえます。
            恐らくは、職人にしか読めない正規表現や3日後に読めなくなる正規表現を嫌ってのものかと。
            なので、今回くらいのものだと、正規表現で書いても可読性が低くなるとは思いません。

            ご指摘のあった部分は、確かに私が書いたコードからして、あんまりきれいじゃないです。

              try:
                i = ls.index('serial')
              except ValueError:
                pass
              else:
                if i > 2 and ls[i-1] == ';':
                  print 'SERIAL:', ls[i-2]
                  continue
              print 'NAME:', ls[0]

            とするのがいいかもしれません。

            --
            1を聞いて0を知れ!
            親コメント
typodupeerror

最初のバージョンは常に打ち捨てられる。

読み込み中...