linux三劍客/代碼屠夫sed,grep,xargs初嘗試

最近公司項(xiàng)目代碼從gogs遷移到gitlab上,項(xiàng)目中大量的pod子組建里的podspec配置,git配置,還有各種腳本里的服務(wù)器地址都需要替換。所以就寫了python腳本全局替換。無意中發(fā)現(xiàn)前同事遺留下來的shell腳本,看上去比python簡(jiǎn)潔得多,其中一個(gè)sed命令引起我的注意,于是研究了一下,確實(shí)強(qiáng)大。本文主要記錄使用sed,grep,xargs工具由簡(jiǎn)到繁最終解決問題的過程,以及自我總結(jié)。

sed簡(jiǎn)介

SED的英文全稱是 Stream EDitor,它是一個(gè)簡(jiǎn)單而強(qiáng)大的文本解析轉(zhuǎn)換工具,在1973-1974年期間由貝爾實(shí)驗(yàn)室的Lee E. McMahon開發(fā),今天,它已經(jīng)運(yùn)行在所有的主流操作系統(tǒng)上了。

SED的典型用途
  • 文本替換
  • 選擇性的輸出文本文件
  • 從文本文件的某處開始編輯
  • 無交互式的對(duì)文本文件進(jìn)行編輯等
示例(Example)
  • 匹配鏈接
sed -n '/http:\/\/.*\/[a-zA-Z]*\.git/ p' UpdatePodScript.sh

在文件UpdatePodScript.sh匹配項(xiàng)目的git地址,p命令是指打印匹配結(jié)果,-n指禁止輸入文件讀入sed模式空間時(shí)默認(rèn)輸出,避免重復(fù)輸出,一般-np同時(shí)使用。

  • 匹配目標(biāo)(需要替換)部分
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
// 用|,@,^,!進(jìn)行分隔,去除\轉(zhuǎn)義符,便于閱讀
sed -n 's@\(http://\)\(.*\)\(/[a-zA-Z]*\(\.git\)\{0,1\}\)@\1GogsAddress\3@ p' LYHttpManager.podspec

括號(hào)內(nèi)就是你需要替換的內(nèi)容,\1是括號(hào)內(nèi)內(nèi)容的別稱,如果有多個(gè)括號(hào)對(duì)應(yīng)別稱就是順延\1、\2\3、... 注意這里括號(hào)需要轉(zhuǎn)義\(xxx\)

  • 匹配并替換目標(biāo)部分
sed -i '' 's@\(http://\)\(.*\)\(/[a-zA-Z]*\(\.git\)\{0,1\}\)@\1GogsAddress\3@g' LYHttpManager.podspec

-i:直接修改讀取的文件內(nèi)容,而不是輸出到終端。
'':取消因?yàn)閙ac系統(tǒng)對(duì)sed命令要求的強(qiáng)制備份。
s:替換命令,格式'/s/oldstring/newstring',將oldstring替換成newstring,默認(rèn)只替換文件里的第一個(gè)oldstring。
g:替換文件里的全部oldstring。

這里有一個(gè)問題,sed正則是不是不支持?,+,我試過匹配不出來。

  • 匹配替換grep搜索的所有結(jié)果(最終命令)
grep -rl 'GitLabAddress' . | sed 's/ /\\ /g' | xargs sed -i '' 's@\(http://\)\(.*\)\(/[a-zA-Z]*\(\.git\)\{0,1\}\)@\1GogsAddress\3@g'
// 因?yàn)槭?對(duì)1的替換,所以不需要正則匹配,把正則換成鏈接字符串。
grep -rl 'GogsAddress' . | sed 's/ /\\ /g' | xargs sed -i '' 's@GogsAddress@GitLabAddress@g'

-r:遍歷目錄及所有子目錄。
-l:只顯示符合條件的文件名(包含路徑)

整個(gè)命令通過|分為三部分:

  1. 獲取包含'GogsAddress'字符串的所有文件名。
  2. 將路徑中空格' '轉(zhuǎn)義成'\ '.
  3. 將'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)
            # 遍歷子項(xiàng)目
            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()

沒有比較兩個(gè)工具好壞的意思,只是直觀比較而已??。

最終一行命令解決問題,而我寫的python腳本幾十行,重點(diǎn)是sed只在終端運(yùn)行就可以,只在終端運(yùn)行就可以,只在終端運(yùn)行就可以,所以稱sed為代碼屠夫也不為過。雖然sed命令簡(jiǎn)潔,但是不太明了,光那轉(zhuǎn)義符都看得頭暈,可讀性不高。but,我還是傾向于用sed解決問題,恩,沒有為什么。??

以上

完全現(xiàn)學(xué)現(xiàn)用,見笑了,就算拋磚引玉吧。

參考資料
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯(cuò)誤還是無法避免 以后資料會(huì)慢慢更新 大...
    數(shù)據(jù)革命閱讀 13,221評(píng)論 2 33
  • 基礎(chǔ)命令 主要的命令和快捷鍵 Linux系統(tǒng)命令由三部分組成:cmd + [options]+[operation...
    485b1aca799e閱讀 1,213評(píng)論 0 0
  • sed與awk實(shí)例 文本間隔 在每一行后面增加一空行 將原來的所有空行刪除并在每一行后面增加一空行。這樣在輸出的文...
    stuha閱讀 2,019評(píng)論 0 20
  • 本文承接之前寫的三十分鐘學(xué)會(huì)AWK一文,在學(xué)習(xí)完AWK之后,趁熱打鐵又學(xué)習(xí)了一下SED,不得不說這兩個(gè)工具真的堪稱...
    mylxsw閱讀 4,515評(píng)論 3 74
  • 本文筆記源自這里——[實(shí)驗(yàn)樓]歡迎大家在下面交流其中有問題的地方喜歡請(qǐng)點(diǎn)收藏,每日更新(全部已親自實(shí)踐). 一. ...
    東皇Amrzs閱讀 4,312評(píng)論 7 54

友情鏈接更多精彩內(nèi)容