linux三剣客/コード屠夫sed,grep,xargs初試み

5066 ワード

最近、会社のプロジェクトコードはgogsからgitlabに移行し、プロジェクト中の大量のpodサブアセンブリのpodspec構成、git構成、そして各種スクリプトのサーバーアドレスを置き換える必要があります.だからpythonスクリプトのグローバル置換を書きました.何気なく前の同僚が残したshellスクリプトがpythonよりずっと簡潔に見えることに気づき、その中のsedコマンドが私の注意を引いたので、研究してみると、確かに強いです.本文は主にsed,grep,xargsツールを用いて簡略から繁へ最終的に問題を解決する過程と自己総括を記録する.
sedの概要
SEDの英語のフルネームはStream EDitorで、簡単で強力なテキスト解析変換ツールで、1973-1974年にベル実験室のLee E.McMahonによって開発され、今日、すべての主流のオペレーティングシステムで実行されています.
SEDの典型的な用途
  • テキスト置換
  • 選択的な出力テキストファイル
  • テキストファイルのどこかから編集
  • テキストファイルをインタラクティブに編集しないなど
  • 例(Example)
  • マッチングリンク
  • sed -n '/http:\/\/.*\/[a-zA-Z]*\.git/ p' UpdatePodScript.sh
    

    ファイルUpdatePodScript.shマッチング git pコマンドとはマッチング結果の印刷-n入力ファイルのsedモード空間への読み込み禁止時のデフォルト出力を指し、重複出力を回避し、一般-np同時使用.
  • 照合対象(置換が必要)部分
  • sed -n 's|http:\/\/\(.*\)\/[a-zA-Z]*\.git|\1| p' UpdatePodScript.sh
    //      git  
    sed -n 's/\(http:\/\/\)\(.*\)\(\/[a-zA-Z]*\.git\)/\1GogsAddress\3/ p' UpdatePodScript.sh
    //  |,@,^,!    ,  \   ,    
    sed -n 's@\(http://\)\(.*\)\(/[a-zA-Z]*\(\.git\)\{0,1\}\)@\1GogsAddress\3@ p' LYHttpManager.podspec
    

    括弧内はあなたが置換する必要がある内容で\1括弧内の内容の別称で、もし複数の括弧が対応する別称があれば順延\1\2\3...ここでカッコはエスケープ\(xxx\)が必要です.
  • ターゲット部分のマッチングおよび置換
  • sed -i '' 's@\(http://\)\(.*\)\(/[a-zA-Z]*\(\.git\)\{0,1\}\)@\1GogsAddress\3@g' LYHttpManager.podspec
    
    -i:端末に出力するのではなく、読み込んだファイルの内容を直接修正します.'':macシステムがsedコマンドに要求した強制バックアップをキャンセルします.s:置換コマンド、フォーマット'/s/oldstring/newstring'oldstringをnewstringに置き換え、デフォルトではファイル内の最初のoldstringのみが置き換えられます.g:ファイル内のすべてのoldstringを置き換えます.
    ここで一つ問題がありますが、sed正則がサポートされていないかどうか?+私はマッチングを試したことがありません.
  • 置換grep検索のすべての結果(最終コマンド)
  • grep -rl 'GitLabAddress' . | sed 's/ /\\ /g' | xargs sed -i '' 's@\(http://\)\(.*\)\(/[a-zA-Z]*\(\.git\)\{0,1\}\)@\1GogsAddress\3@g'
    //    1 1   ,         ,          。
    grep -rl 'GogsAddress' . | sed 's/ /\\ /g' | xargs sed -i '' 's@GogsAddress@GitLabAddress@g'
    
    -r:ディレクトリおよびすべてのサブディレクトリを巡回します.-l:該当するファイル名のみ(パスを含む)
    命令全体が通過し|3つの部分に分かれています.
  • 'GogsAddress'文字列を含むすべてのファイル名を取得します.
  • パス中のスペース''を''.
  • 'GogsAddress'を'GitLabAddress'に置き換えます.

  • sedとpython
  • sed
  • grep -rl 'GogsAddress' . | sed 's/ /\\ /g' | xargs sed -i '' 's@GogsAddress@GitLabAddress@g'
    
  • python
  • #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    
    import os
    import re
    import sys
    
    # profile    
    # ROOT_PATH = '/Users/wans/Documents/iOSUser/Code/LYLawyerPlatform_User'
    
    GITLAB_HOST_ADDRESS = "GitLabAddress"
    ROOT_PATH = os.getcwd()
    
    def replace_address(address):
        fo = open(address,'r+')
        content = fo.read()
    
        pattern = re.compile(r'http://(.+)/(\w+)(\.git)*')
        match = pattern.search(content)
        if match:
            old_module_address = match.group(1)
    
            content = content.replace(old_module_address,GITLAB_HOST_ADDRESS)
    
            fo = open(address, 'w')
            fo.write(content)
            fo.flush()
    
        if fo:
            fo.close()
    
    def main():
    
        files = os.listdir(ROOT_PATH)
        for subdir in files:
            subdir = os.path.join(ROOT_PATH,subdir)
            if os.path.isdir(subdir):
                module_files = os.listdir(subdir)
                #      
                for module_subdir in module_files:
                    module_subdir = os.path.join(subdir,module_subdir)
                    if module_subdir.endswith('.git'):
                        module_dir = os.path.join(module_subdir,"config")
                        print module_dir
                        if os.path.exists(module_dir):
                            replace_address(module_dir)
    
                    if module_subdir.endswith('Example'):
                        module_dir = os.path.join(module_subdir,"Podfile")
                        print module_dir
                        if os.path.exists(module_dir):
                            replace_address(module_dir)
    
                    if module_subdir.endswith('.podspec'):
                        print module_subdir
                        replace_address(module_subdir)
    
                    if module_subdir.endswith('UpdatePodScript.sh'):
                        print module_subdir
                        replace_address(module_subdir)
    
    if __name__ == '__main__':
        main()
    

    二つの道具の善し悪しを比較する意味はなく、直観的に比較するだけです.
    最終的な1行のコマンドは問題を解決して、私が書いたpythonスクリプトは数十行で、重点はsedが端末で実行するだけでいいことで、端末で実行するだけでいいので、sedをコード屠殺者と呼ぶのも過言ではありません.sed命令は簡潔であるが,よく分からず,光那転義符はめまいがし,可読性が高くない.but、私はやはりsedで問題を解決する傾向があります.うん、なぜかありません.
    以上
    完全に現学現用して、笑って、レンガを投げて玉を引いてもいいでしょう.
    参考資料
  • 30分学会SED
  • xargsコマンド詳細、xargsとパイプの違い