<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          批量處理文件,除了 Python,不妨試試 VIM!

          共 5636字,需瀏覽 12分鐘

           ·

          2021-07-02 01:49

          ↑↑↑關(guān)注后"星標(biāo)"簡(jiǎn)說(shuō)Python

          人人都可以簡(jiǎn)單入門(mén)Python、爬蟲(chóng)、數(shù)據(jù)分析
           簡(jiǎn)說(shuō)Python推薦 
          來(lái)源:早起Python
          作者:大奎

          大家好,我是老表

          在之前的辦公自動(dòng)化系列文章,我們大多基于 Python 實(shí)現(xiàn),因?yàn)槭褂?Python 具有靈活、強(qiáng)大的特點(diǎn)。使用 VIM 具有快速、可視化的優(yōu)勢(shì)。兩者對(duì)大量同構(gòu)文本進(jìn)行修改,可大幅提高工作效率。但相較于編寫(xiě) Python 程序,VIM 可視化執(zhí)行更勝一籌。

          這也提示我們,Python 不是萬(wàn)能的——至少在某些方面、某些場(chǎng)景下,不一定是最優(yōu)解。合適的工具運(yùn)用到合適的場(chǎng)合是效率最高的方式。不能自己是錘子,看什么就都是釘子。

          在對(duì) VIM 不熟悉的用戶(hù)看來(lái),VIM 的操作過(guò)程可能更復(fù)雜、難懂。但這是先入為主的印象,VIM 處理文本還是很方便快捷的:我們有了 Python 這把錘子,不排斥再來(lái) VIM 這個(gè)鋸嘛,這樣才能“工欲善其事,必先利其器”。本文將對(duì)比使用 Python 和 VIM 對(duì)同一個(gè)文本編輯任務(wù)處理的情況。



          01

          需求說(shuō)明



          有大量類(lèi)似結(jié)構(gòu)的文本文件需要處理,目錄結(jié)構(gòu)如下:

          E:.
          └─content
              ├─a
              │ └──content.txt
              ├─b
              │ └──content.txt
              └─c
                └──content.txt 

          其中的每個(gè)文件 content .txt內(nèi)容結(jié)構(gòu)如下:

          <vsbimg src="/_vsl/012A716D176AFA6EBBAF64BD4CB63BCA/994A4168/AE5BB"></vsbimg>
          <vsbimg src="/_vsl/2ADBFFCE33AAE9B2E79E758EF6AD5626/CEFD12BB/A8DC5"></vsbimg>

          要求是:

          • <vsbimg></vsbimg> 標(biāo)簽改為 <img></img> 標(biāo)簽。
          • /_vsl/012A7 表示的相對(duì)地址,變成另一個(gè) URL 地址,如 http://image.xx.com/image/
          • 將 src 的最后兩個(gè)/改為 _。
          • 將整個(gè) src 最后加上圖片后綴 .png。

          修改后的文件為:

          <img src="http://image.xx.com/image/16D176AFA6EBBAF64BD4CB63BCA_994A4168_AE5BB.png"></img>
          <img src="http://image.xx.com/image/FCE33AAE9B2E79E758EF6AD5626_CEFD12BB_A8DC5.png"></img>



          02

          Python實(shí)現(xiàn)



          首先讓我們用 Python 編寫(xiě)程序來(lái)完成,代碼比較簡(jiǎn)單,但面對(duì)如此簡(jiǎn)單的問(wèn)題,寫(xiě)一個(gè)程序還是“高射炮打蚊子” 了。而且調(diào)試 Python 正則表達(dá)式,并不是一個(gè)直觀(guān)的過(guò)程。

          import os
          import re


          def rep(strs):
              strs = re.sub(r'<vsbimg',r'<img',strs)
              strs = re.sub(r'<\/vsbimg',r'</img',strs)
              strs = re.sub(r'(/_vsl/.*?)/',r'\1_',strs)
              strs = re.sub(r'(/_vsl/.*?)/',r'\1_',strs)
              strs = re.sub(r'(src=".*?)"',r'\1.png"',strs)
              strs = re.sub(r'src="/_vsl/.{5}',r'src="http://image.x.com/image/',strs)
              return strs


          def op(fn):
              fn2 = os.path.join(os.path.split(fn)[0],os.path.split(fn)[1]+'new')
              with open(fn,encoding='utf-8') as f,open(fn2,'w',encoding='utf-8') as f2:
                  for l in f.readlines():
                      l = rep(l)
                      f2.write(l)

          for r,_,fs in os.walk('content'):
              for f in fs:
                  if f.endswith('txt'):
                      fn = os.path.join(r,f)
                      op(fn)

          殺雞不用牛刀,咱們改用 VIM 試試。

          VIM 最主要好處就是:構(gòu)造查找正則表達(dá)式時(shí)結(jié)果可視化,這樣就可以逐步求精地寫(xiě)正則表達(dá)式,反之剛才寫(xiě)程序時(shí),我得來(lái)回測(cè)試,十分費(fèi)力。



          03

          VIM實(shí)現(xiàn)



          下面是使用 VIM 實(shí)現(xiàn)需求所需要注意的幾點(diǎn)

          • 本例使用 VIM 中的 :%s 替換指令很容易完成替換操作。正則表達(dá)式構(gòu)造需要慢慢來(lái)。
          • 如果牽涉到復(fù)雜替換時(shí),還需要對(duì)搜索結(jié)果分組,以便使用分組結(jié)果。
          • 為了批量完成序列替換操作,需要將操作寫(xiě)入批處理腳本,再用 :source 執(zhí)行腳本。
          • 以上操作在單文件中執(zhí)行,為了在許多文件中同時(shí)完成,需要使用緩沖區(qū)執(zhí)行 :bufdo 命令。

          3.1 構(gòu)造正則表達(dá)式搜索

          為了替換 <vsbimg,我們構(gòu)造一個(gè)查找正則表達(dá)式。

          構(gòu)造出的表達(dá)式如下:

          /<vsbimg

          這個(gè)表達(dá)式搜索了 <vsbimg 開(kāi)頭的所有內(nèi)容。

          / 指令后按向上箭頭表示上一次輸入的查詢(xún)歷史。按 q/ 表示所有查詢(xún)歷史,可以在此歷史上修改,這樣就可以逐步精化。

          3.2 替換

          常規(guī)替換指令 :%s/pattern/string/g,留空的查詢(xún)域表示上次搜索的結(jié)果。在上步查詢(xún)基礎(chǔ)上,我們可以使用 :%s//<img/g 的方式完成更改。

          這個(gè)操作很重要:很多復(fù)雜的正則表達(dá)式,不可能一步直接構(gòu)造出來(lái);采用搜索的方法,可以高亮顯示每次的搜索結(jié)果,進(jìn)而改進(jìn)正則表達(dá)式。而替換時(shí)留空查找域,直接表示上次搜索結(jié)果,極大方便了替換操作。使一步替換操作轉(zhuǎn)換為:搜索,替換兩步,降低了難度,提高了效率。

          注意以下替換語(yǔ)句,使用了 \ 轉(zhuǎn)義字符來(lái)匹配 </vsbimg> 的特殊字符 \

          :%s/<\/vsbimg/<\/img/g

          3.3 搜索結(jié)果分組、使用

          在對(duì) \ 轉(zhuǎn)換為 _ 的操作中,我們需要記住之前的匹配對(duì)象,用來(lái)在替換時(shí)作為不改變的內(nèi)容引用。

          這里用 () 圈起來(lái)需要分組的部分,在搜索或者替換部分用 \1 表示第一個(gè)分組,以此類(lèi)推。具體看代碼:

          :%s/\("\/_vsl\/.\{-1,}\)\//\1_/g 

          因?yàn)橛袃蓚€(gè) \,所以需要執(zhí)行兩次。

          替換域里的 \1 指代的是 () 中的匹配內(nèi)容,也就是 src\_vsb/ 之后遇到的第一個(gè) \ 為止的內(nèi)容。當(dāng)替換時(shí),我們依然把這部分,用 \1 使用上,只是把 \ 改為\_

          3.4 非貪婪模式

          上例子可見(jiàn) .\{-1,} 的代碼,這是對(duì)任意字符進(jìn)行非貪婪匹配,以縮小 / 適配范圍,適配到第一個(gè) / 為止,不再繼續(xù)貪婪最大適配。

          在給 src 添加 .png 后綴時(shí),也使用了分組和非貪婪概念。將 src 到第一個(gè)"的內(nèi)容視為一個(gè)分組,然后替換為分組內(nèi)容和 .png"

          :%s/\(src=".\{-1,}\)"/\1.png"/g

          將相對(duì)地址修改為 URL 時(shí),URL 部分需要進(jìn)行很多次轉(zhuǎn)義。

          :%s/src="\/_vsl\/.\{5\}/src="http:\/\/192\.168\.22\.117\/cnv\/jflyfox\/mtg\/cnvImage\//g

          最后,我們把以上修改保存進(jìn)原文件:w

          以上,我們通過(guò)搜索和替換操作,完成了對(duì)單個(gè)文件的修改。

          如果對(duì)每一個(gè)文件都執(zhí)行如上的程序,就顯得比較復(fù)雜了,好在 VIM 支持批處理操作。

          3.5 批處理文件執(zhí)行 source

          這里,我們將以上操作步驟,寫(xiě)到 oper.vim 文件中去。

          :%s/<vsbimg/<img/ge
          :%s/<\/vsbimg/<\/img/ge
          :%s/\("\/_vsl\/.\{-1,}\)\//\1_/ge
          :%s/\("
          \/_vsl\/.\{-1,}\)\//\1_/ge
          :%s/\(src=".\{-1,}\)"/\1.png"/ge
          :%s/src="
          \/_vsl\/.\{5\}/src="http:\/\/192\.168\.22\.117\/cnv\/jflyfox\/mtg\/cnvImage\//ge
          :w

          在另一個(gè)新的待處理文件中,我們輸入 :source oper.vim,就將以上所有操作在新文件中重做。

          操作一個(gè)新文件可行了,如何操作大批量的文件呢?

          q: 表示所有替換歷史,將這些替換命令拷貝出來(lái),避免輸入帶來(lái)的麻煩和錯(cuò)誤。

          3.6 緩沖區(qū)批量執(zhí)行 bufdo

          VIM 的 Buffer 緩沖區(qū),相當(dāng)于內(nèi)存。當(dāng)我們具體修改某個(gè)文件時(shí),實(shí)際是在內(nèi)存中對(duì)他進(jìn)行修改,只有當(dāng)輸入 :w 命令時(shí),修改才寫(xiě)回硬盤(pán)。

          使用 vim a.txt b.txt 指令,一次性打開(kāi)兩個(gè)文件,當(dāng)前訪(fǎng)問(wèn)和修改的是 a.txt。使用指令 :bnext 在緩沖區(qū)之間跳轉(zhuǎn)。指令 :ls 列出了當(dāng)前所有緩沖區(qū)文件。

          使用 vim *.txt,批量打開(kāi) txt 后綴的文件。

          在當(dāng)前緩沖區(qū)列表上的所有文件執(zhí)行命令,輸入 :bufdo excommand

          本文中我們打開(kāi)目錄 a,b,c 下的 content.txt 文件,使用 vim content/*/*.txt 即可。在打開(kāi)的窗口中執(zhí)行 :ls 即可查看當(dāng)前緩沖區(qū)文件。確認(rèn)無(wú)誤后,執(zhí)行 :bufdo source oper.vim ,即可完成對(duì)所有緩沖區(qū)文件的修改。

          抑制錯(cuò)誤:當(dāng)我們使用以上 vim 腳本時(shí),很容易因?yàn)樗阉饕?guī)則或者文本問(wèn)題導(dǎo)致出錯(cuò),進(jìn)而導(dǎo)致腳本停止。在每個(gè)替換語(yǔ)句之后加上 e ,用來(lái)表示抑制錯(cuò)誤,就可以修正這個(gè)問(wèn)題。




          04

          小結(jié)



          使用 VIM 中的替換指令很容易完成操作。但正則表達(dá)式構(gòu)造需要慢慢來(lái)。逐步求精,還可能需要分組和非貪婪模式。批處理文件 .vim 和 :source 命令可以大大簡(jiǎn)化工作。緩沖區(qū)列表執(zhí)行 :bufdo 命令則進(jìn)一步提高工作效率。

          VIM 編輯器處理這個(gè)問(wèn)題,使用的技巧都比較通用,可以遷移到其他文本處理任務(wù)中。最主要的是,構(gòu)造正則表達(dá)式的過(guò)程是直接反饋、可視化的,利于構(gòu)造復(fù)雜表達(dá)式。

          Python 不是萬(wàn)能的——至少在某些方面、某些場(chǎng)景下,不一定是最優(yōu)解。合適的工具運(yùn)用到合適的場(chǎng)合是效率最高的方式。不能自已是錘子,看什么就都是釘子。


          --END--



          掃碼即可加我微信

          老表朋友圈經(jīng)常有贈(zèng)書(shū)/紅包福利活動(dòng)


          學(xué)習(xí)更多:
          整理了我開(kāi)始分享學(xué)習(xí)筆記到現(xiàn)在超過(guò)250篇優(yōu)質(zhì)文章,涵蓋數(shù)據(jù)分析、爬蟲(chóng)、機(jī)器學(xué)習(xí)等方面,別再說(shuō)不知道該從哪開(kāi)始,實(shí)戰(zhàn)哪里找了

          優(yōu)秀的讀者都知道,“點(diǎn)贊”傳統(tǒng)美德不能丟 

          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧洲综合网 | 18色性在线 | 欧美性爱乱伦视频网 | 免费 69视频 | 欧美一级性爱 |