AWK コマンドをまねたものを Python で実装。

実行例
  • pyawk.py は AWK コマンド相当のファイル。
  • pyawk0010.py は AWK スクリプト相当のファイル。
py pyawk.py pyawk0010
pyawk.py
# -*- coding: utf-8 -*-


import sys
import re


nArgument = len( sys.argv )

if nArgument == 1 :
    print( '書式' )
    print( 'py pyawk <処理内容 .PY ファイル> <処理対象ファイル>' )
    exit( 0 )

if nArgument < 3 :
    print( '引数が不正です' )
    exit( 1 )


try :
    f = open( sys.argv[1] )
    contentFunc = f.read()
except Exception:
    print( '処理内容 .PY ファイルを読み込めませんでした。' )
    exit( 1 )
finally :
    f.close()


try :
    exec( contentFunc )
except Exception :
    print( '処理内容 .PY ファイルの内容が不正です。' )
    exit( 1 )


try :
    f = open( sys.argv[2] )
    lines = f.readlines()
except Exception :
    print( '処理対象ファイルを読み込めませんでした。' )
    exit( 1 )
finally :
    f.close()


length = len( lines )



#---- 準備
if length > 0 :
    indexFirst = 0
    indexLast = length - 1
    lengthStr = len( lines[0] )
    lineFirst = lines[0][:lengthStr - 1]
    lengthStr = len( lines[length - 1] )
    lineLast  = lines[length - 1][:lengthStr - 1]
else :
    indexFirst = -1
    indexLast = -1
    lineFirst = ''
    lineLast  = ''


info = { 'LineNum':length, 'lines':lines, 'target':sys.argv[2] }
user = {}

result = 0


#---- 準備処理
try :
    Prepare( info, user )
finally :
    'No-Process'

if result >= 0 :
    #---- 開始処理
    result = Begin( info, user, indexFirst, lineFirst )

    if result >= 0 :
        #---- 主処理
        index = 0
        for l in lines :
            lengthStr = len( l )
            result = Main( info, user, index, l[:lengthStr - 1] )

            if result < 0 :
                break

            # 行インデックスを進める
            index += 1

    #---- 終了処理
    End( info, user, indexLast, lineLast )

#---- 最終処理
try :
    Cleanup( info, user )
finally :
    'No-Process'
pyawk0010.py
# -*- coding: utf-8 -*-

# この .PY は pyawk.py から呼ばれます。
#
# 各関数への引数
#     info
#         読み込んだファイルの情報を格納します。
#     user
#         この .PY で任意の値を格納できる連想配列(辞書)です。
#     index
#         読み込まれた行の行番号(0 ベース)。
#         1 行もないファイルは -1 になります。
#         Begin 関数においては 0 または -1 になります。
#         End 関数においては行数 - 1 または -1 になります。
#         Main 関数においては 0 ~ 行数 - 1 になります。
#     line
#         読み込んだ行の内容です。
#         index が -1 の場合 '' になります。
#
# Begin 関数
#     最初の行を処理します。
#     1 回呼ばれます。
#     Main 関数の前に呼ばれます。
#     戻り値が 0 未満の場合は Main 関数が飛ばされ End 関数が呼ばれます。
#     戻り値が 0 以上の場合は Main 関数が続いて呼ばれます。
# End 関数
#     最後の行を処理します。
#     1 回呼ばれます。
#     Main 関数の後に呼ばれます。
# Main 関数
#     最初の行 ~ 最後の行を処理します。
#     行数分呼ばれます。
#     戻り値が 0 未満の場合は Main 関数が飛ばされ End 関数が呼ばれます。
#     戻り値が 0 以上の場合は Main 関数が続いて呼ばれます。
# Prepare 関数
#     Begin 関数の前に呼ばれます。
#     この関数は定義を省略できます。
#     戻り値が 0 未満の場合は Begin / Main / End 関数が飛ばされ Cleanup 関数が呼ばれます。
#     戻り値が 0 以上の場合は Begin / Main / End / Cleanup 関数が続いて呼ばれます。
# Cleanup 関数
#     End 関数の後に呼ばれます。
#     この関数は定義を省略できます。
#
# 関数の呼ばれる順番
#     1. Prepare ... 1 回呼ばれる
#     2. Begin   ... 1 回呼ばれる
#     3. Main    ... n 回呼ばれる
#     4. End     ... 1 回呼ばれる
#     5. Cleanup ... 1 回呼ばれる
#


# この関数は定義を省略できます
def Prepare( info, user ) :

    print( 'called Prepare' )

    return 0


# この関数は定義を省略できます
def Cleanup( info, user ) :

    print( 'called Cleanup' )


# この関数は必須
def Begin( info, user, index, line ) :

    print( f'No {index}: {line}' )

    return 0


# この関数は必須
def End( info, user, index, line ) :

    print( f'No {index}: {line}' )


# この関数は必須
def Main( info, user, index, line ) :

    print( f'No {index}: {line}' )

    return 0