song.yz@foxmail.com wechat: math-box

blog

代码块批量替换



在程序设计中,经常有一些批量代码块(文本)需要替换。如HTLM开发,其导航栏和footer栏,如果网页较少,则可以手动复制相同的代码块。 当网页非常多的时候,如果还这么做无疑是灾难级的维护。现在的javascript管理工具应该是有针对这一问题处理的场景,不过我也不太清楚,没用过。这一想到的第一方法是 把相同的代码另存为文本文件,然后用JavaScript加载。

JavaScript代码形式如下:

            




 
 
            
         


这样做的好处是一次编写公用文件,只要在需要加载的地方引入即可。但是也有坏处,有些浏览器不会及时刷新加载的javascrip修改的内容。 另外,在引入一些框架后,容易让以上方法失效,我自己的经验是这样的。不过,也可能是有其他原因,没查出。

这里想到的第二个方法是自己编写代码块替换函数。代码文件名为updateNavfoot.py, 代码如下:
 
# encoding:utf-8
#!/usr/bin/env python
"""
------------------------------------------ main script
 Author  :  song.yz                       Copyrigt (C)
 Purpose :  2023-2-6 12:22                   (V 1.0) 
               
 python -m pdb *.py
 Email        : song.yz@foxmail.com
 Copyrigt (C) : Chinese Academy of Sciences               
               All rights reserved,  2023
-----------------------------------------------------  
"""
import sys
import csv
import os 

 
def main(finName,configList):
    """
    -----------------------------------------------------
    Author  :  song.yz                     Copyrigt (C)                    
    Purpose :  2023-2-6 12:22                 (V 1.0) 
                
         the tag of HTML sample 
    -----------------------------------------------------
    Input  parameters  :
        finName ----  HTML file name which will be update by pubString
        pubfileName -- public file name 
        key word        
    Output parameters  :               
   
    ----------------------------------------------------
    """
    fout = open('new-'+finName,'wt')
    fin  = open(finName,'rt')
    while True :
        line = fin.readline()
        if not line:
            break 
        lineType,pubfileName = lineInfo(line,configList)
        if lineType == 0:
            fout.write(line) 
        
        if lineType == 1:
            ftmp = open(pubfileName,'rt')
            strtmp = ftmp.read()
            
            fout.write(line)
            #keep the initial tag 
            fout.write(strtmp)
            
            while True :
                line = fin.readline()
                if not line:
                    break 
                lineType,pubfileName = lineInfo(line,configList)
                if lineType == 2:
                    fout.write('\n'+line)
                    break 
                    
            #keep the initial tag 
    fout.close()
    fin.close()
    return 0


def  lineInfo(line,configList):
    """
    -----------------------------------------------------
    Author  :  song.yz                     Copyrigt (C)                    
    Purpose :  2023-2-7 11:31                 (V 1.0) 
       get the type of a string which is a line of the HTML file 
       
    -----------------------------------------------------
    Input  parameters  :
                
    Output parameters  :               
          lineType  ---- 0   norm line 
                         1   begin flag
                         2   end flag 
    ----------------------------------------------------
    """
    lineType = 0
    lineList = line.split()
    pubfileName = 'xx'
    if len(lineList) == 3:
        for configLine in configList:
            configLineList = configLine[0].split()
            # split the line to list 
            if  lineList[0] == '':
                if lineList[1] == configLineList[0]:
                    lineType = 1
                    pubfileName = configLineList[2]
                if lineList[1] == configLineList[1]:
                    lineType = 2
    return lineType,pubfileName
                    
def getConfig():
    """
    -----------------------------------------------------
    Author  :  song.yz                     Copyrigt (C)                    
    Purpose :  2023-2-7 12:39                 (V 1.0) 
           read the cvs config file  and trans the 
           string to list 
           config file sample :
              navBegin         navEnd     navpub.html
             footBegin        footEnd    footpub.html
    -----------------------------------------------------
    Input  parameters  :
                
    Output parameters  :               
   
    ----------------------------------------------------
    """
    fileConfig =  open("config.csv",'rt')
    configString = csv.reader(fileConfig)
    configList = list(configString)
    fileConfig.close()
    return configList

def  updateFiles():
    """
    -----------------------------------------------------
    Author  :  song.yz                     Copyrigt (C)                    
    Purpose :  2023-2-8 10:17                 (V 1.0) 
                
    -----------------------------------------------------
    Input  parameters  :
                
    Output parameters  :               
   
    ----------------------------------------------------
    """
    currentPath = os.getcwd()
    print('currentPath: ' +currentPath)
    fin  = open("filelist.cfg",'rt')
    configList = getConfig()
    while True:
        line = fin.readline()
        if not line:
            break 
        if line[0] == '#':
            continue 
        words = line.split()
        filePath = words[0]
        fileName = words[1]
        os.chdir(filePath)
        print("current path"+ os.getcwd())
        main(fileName,configList)
        os.rename(fileName,fileName+'.bak')
        os.rename('new-'+fileName,fileName)
    fin.close()
    os.chdir(currentPath)
    print('currentPath: ' +currentPath)
        
def  deletBakFiles():
    """
    -----------------------------------------------------
    Author  :  song.yz                     Copyrigt (C)                    
    Purpose :  2023-2-8 10:30                 (V 1.0) 
                
    -----------------------------------------------------
    Input  parameters  :
                
    Output parameters  :
    ----------------------------------------------------
    """
    currentPath = os.getcwd()
    print('currentPath: ' +currentPath)
    fin  = open("filelist.cfg",'rt')
    while True:
        line = fin.readline()
        if not line:
            break 
        if line[0] == '#':
            continue 
        words = line.split()
        filePath = words[0]
        fileName = words[1]
        os.chdir(filePath)
        print("current path"+ os.getcwd())
        if os.path.exists(fileName+'.bak'):
            os.remove(fileName+'.bak')
    fin.close()
    os.chdir(currentPath)
    print('currentPath: ' +currentPath)
    
if __name__=='__main__':
    mode = sys.argv[1]
    if mode == 'update':
        updateFiles()
    if mode == 'delete':
        deletBakFiles()         
         
        


以上软件需要配置两个文件,一个是需要更新替换的目标文件列表,因为可以直接处理多目标。文件名为filelist.cfg,文件内容形式如下
  /home/astrodynamics/   index0.html
  ./course                index.html
  ./gradinfo              index.html
其中第一列为文件路径,第二列为需要替换代码块的目标文件。

第二个文件用来标识目标文件中要替换的内容,和用什么文件替换。其配置文件为config.csv,文件内容形式如下
   navBegin         navEnd       ../pubhtml/nav.html
  footBegin        footEnd       ../pubhtml/footer.html


该文件共三列,第一列为替换标识开始关键词,第二列为替换结束关键词。 第三列为公共代码块文本文件。

该程序可以对多个目标替换,可以实现对同一个目标多处替换。 替换使用的命令为

    python updateNavfoot.py  update

其中update为命令行关键词,用来标识替换更新。在执行改命令后,会在所有原目标文件目录下生成一个后缀为 .bak的备份文件,防止误操作。改文件为替换前的文件。 如果要批量删除备份文件,可以使用
    python updateNavfoot.py  delete
则会删除所有更新操作时产生的备份文件。


文件遍历方法,在python中,可以用os.walk进行文件遍历。在文件很多 情况下,可以先遍历文件然后转到使用以上替换。 代码如下
 
import os
from os.path import join

def listfiles(homePath):
    """
    -----------------------------------------------------
    Author  :  song.yz                     Copyrigt (C)                    
    Purpose :  2023-2-11 20:02                 (V 1.0) 
        遍历HTML文件                
    -----------------------------------------------------
    Input  parameters  :
                
    Output parameters  :               
   
    ----------------------------------------------------
    """
    for (root,dirs,files) in os.walk(homePath):
        for myfile in files:
            if myfile[-5:] =='.html':
                print(root+' '*5+ myfile)
if __name__=='__main__':
    listfiles('./research/')
    listfiles('./academics/')
    listfiles('./students/')