shell实现str.replace更改日期格式

本文介绍了如何在 Shell 脚本中使用变量替换进行文本操作,包括替换所有匹配项、替换第一个匹配项、删除部分文本以及转换日期格式。示例代码详细展示了如何实现这些功能,对于理解和运用 Shell 脚本处理字符串非常有帮助。

替换所有

echo ${MESSAGE//e/E}

替换第一个

echo ${MESSAGE/e/E}

Code:

$ MESSAGE="Develop a passion for learning. If you do, you will never cease to grow."
$ echo ${MESSAGE}
Develop a passion for learning. If you do, you will never cease to grow.

# Replace part of the text.
# Replace "passion" with "desire":
$ echo ${MESSAGE/passion/desire}
Develop a desire for learning. If you do, you will never cease to grow.

# Remove part of the text.
# Here, remove "passion":
$ echo ${MESSAGE/passion}
Develop a for learning. If you do, you will never cease to grow.

# Replace the first match in the text.
# Here, "e" becomes "E":
$ echo ${MESSAGE/e/E}
DEvelop a passion for learning. If you do, you will never cease to grow.
$ 

# Replace all matches in the text, by adding an extra slash (/).
# Here, all "e" become "E":
$ echo ${MESSAGE//e/E}
DEvElop a passion for lEarning. If you do, you will nEvEr cEasE to grow.

替换日期

2020-11-16  2020/11/16

$ echo ${MESSAGE//e/E}

$ date_str='2020-11-16'

$ echo ${date_str//-/\}
2020/11/16


 

参考

https://www.shellscript.sh/tips/pattern-substitution/

把你说的修改进我的代码再把完整代码给我: import os import subprocess import sys import time import re def curFilePath(): """返回项目根目录 D:\Beta_Interpreter\online_test""" if hasattr(sys, 'frozen'): return os.path.dirname(sys.executable) else: return os.path.dirname(os.path.dirname(__file__)) def getRelPath(relStr): return os.path.abspath(os.path.join(curFilePath(), relStr)) g_logLevel = ['INVALID', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'] # g_logLevel 是一个列表,定义了日志的级别。g_logModule 是一个字典,将模块的十六进制编号映射到模块名称 g_logModule = { 0x00 : 'HIVIEW', 0x01 : 'SAMGR', 0x02 : 'UPDATE', 0x03 : 'ACE', 0x04 : 'APP', 0x05 : 'AAFWK', 0x06 : 'GRAPHIC', 0x07 : 'MEDIA', 0x08 : 'DMA', 0x09 : 'SEN', 0x0A : 'SCY', 0x0B : 'XTS', 0x0C : 'SOFTBUS', 0x0D : 'PWM', 0x0E : 'UIKIT', 0x0F : 'GLOBAL', 0x10 : 'DATAMGR', 0x1E : 'HISI', 0x1F : 'COMMU', 0x20 : 'NV', 0x21 : 'BSP', 0x22 : 'DM', 0x23 : 'PM', 0x24 : 'LCD', 0x25 : 'GPS', 0x26 : 'BT', 0x27 : 'NFC', 0x28 : 'SVRAUDIO', 0x29 : 'FTM', 0x2A : 'SVR', 0x2B : 'APPUI', 0x2C : 'AST', 0x2D : 'FIT', 0x2E : 'ALG', 0x2F : 'HRM', 0x30 : 'TLV', 0x31 : 'WIFI', 0x32 : 'INPUT', 0x33 : 'RFID', 0x34 : 'EARSDK', 0x35 : 'SVCOMMU', 0x36 : 'RSMC', 0x37 : 'UWB', 0x38 : 'WATCHEAR', 0x39 : 'PAIR', 0x3A : 'DRVAUDIO', 0x3B : 'BRIGHT', 0x3C : 'FITUI', 0x3D : 'DIALUI', 0x3E : 'FMKUI', 0x3F : 'HRMUI' } class BIN_INFO(): # 该类用于存储二进制文件的相关信息,包括起始地址、结束地址、二进制内容、文件路径、内容字典和标志。 def __init__(self, flag): self.start_address = 0 self.end_address = 0 self.bin_content = [] self.bin_path = "" self.bin_dict = {} self.flag = flag class LogProcessThread(): # 该类用于处理日志文件,初始化时接收日志文件和各种二进制文件信息。 def __init__(self, log_file, gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info): self.log_file = log_file self.gpu_info = gpu_info self.rom_info = rom_info self.xip_info = xip_info self.itcm_info = itcm_info self.sram_info = sram_info self.reverse1_info = reverse1_info self.reverse2_info = reverse2_info def find_address_by_bin(self, logStr, key_index, num_list, bin_files_dict): # 该方法用于在二进制文件中查找地址对应的字符串,并替换日志字符串中的 % s占位符。 s_list = [] for i in range(len(logStr)): if logStr[i] == "%" and i != len(logStr) - 1: s_list.append(logStr[i: i + 2]) for i in range(len(s_list)): if s_list[i] == "%s": for j in key_index: if num_list[i] > j: address = num_list[i] - j new_s = "" if (bin_files_dict.get(j).bin_dict.__contains__(address) == False): new_s = str(bin_files_dict.get(j).bin_content[address:-1]).split('\\x00', 1)[0] new_s = new_s[2: len(new_s)] if isText(logStr): new_s = new_s.replace('\r', '') new_s = new_s.replace('\n', '') new_s = new_s.replace('{public}', '') new_s = new_s.replace('{private}', '') new_s = new_s.replace('%ll', '%') new_s = new_s.replace('%p', '%x') bin_files_dict.get(j).bin_dict[address] = new_s else: new_s = 'NULL' else: new_s = bin_files_dict.get(j).bin_dict[address] num_list[i] = new_s break return num_list def return_format_str(self, logStr, logContent, logContentIndex, num): # 该方法用于从日志内容中提取格式化字符串的参数。 num_list = [] index = logStr.find('%', 0, len(logStr)) temp_num = 0 while (index >= 0) or (temp_num < num): startLogIndex = logContentIndex + 12 + temp_num * 4 endLogIndex = logContentIndex + 12 + (temp_num + 1) * 4 if "%d" in logStr[index:index + 2]: logArgOne = int.from_bytes(logContent[startLogIndex:endLogIndex], "little", signed=True) num_list.append(logArgOne) else: logArgOne = int.from_bytes(logContent[startLogIndex:endLogIndex], "little", signed=False) num_list.append(logArgOne) index = logStr.find('%', index + 1, len(logStr)) temp_num += 1 return num_list def start_parse_v1r6(self): # 该方法是核心的日志解析方法,从日志文件中读取内容,检查日志的头部信息、级别、模块和参数数量,提取日志字符串和参数,格式化日志信息并写入结果文件。 with open(self.log_file, 'rb') as logFile: #logFile = open(self.log_file, 'rb') logFileSize = os.path.getsize(self.log_file) logFile.seek(0, 0) logContent = logFile.read(logFileSize) list1 = [self.gpu_info, self.rom_info, self.xip_info, self.itcm_info, self.sram_info, self.reverse1_info, self.reverse2_info] bin_files_dict = {} for i in list1: if i.start_address != 4294967295 and i.start_address != 0: bin_files_dict[i.start_address] = i key_index = sorted(bin_files_dict.keys(), reverse=True) logResultFile = open(logFileArg + '_offline.txt', 'w', encoding='utf8', errors='ignore') logContentIndex = self.find_head_index(logContent, 0) while logContentIndex <= logFileSize - 12: if logContent[logContentIndex] == 0xED: # check the log level is in range or not logLevel = logContent[logContentIndex + 1] if (logLevel & 0x7F) >= 0x06: logContentIndex = self.find_head_index(logContent, logContentIndex + 1) continue # check the log module is in range or not logModule = logContent[logContentIndex + 2] # if g_logModule.__contains__(logModule) == False: # logContentIndex = logContentIndex + 1 # continue # check the log arguments is larger than 6 or not logArgNum = logContent[logContentIndex + 3] if logArgNum > 6: logContentIndex = self.find_head_index(logContent, logContentIndex) continue logTime = int.from_bytes(logContent[logContentIndex + 4: logContentIndex + 8], "little") logAddress = int.from_bytes(logContent[logContentIndex + 8: logContentIndex + 12], "little") logStr = 'NULL' if logLevel < 0x06: for i in key_index: if logAddress > i: address = logAddress - i if (bin_files_dict.get(i).bin_dict.__contains__(address) == False): logStr = str(bin_files_dict.get(i).bin_content[address:-1]).split('\\x00', 1)[0] logStr = logStr[2: len(logStr)] if isText(logStr): logStr = logStr.replace('\\r', '') logStr = logStr.replace('\\n', '') logStr = logStr.replace('{public}', '') logStr = logStr.replace('{private}', '') logStr = logStr.replace('%ll', '%') logStr = logStr.replace('%p', '%x') bin_files_dict.get(i).bin_dict[address] = logStr else: logStr = 'NULL' else: logStr = bin_files_dict.get(i).bin_dict[address] break if (logArgNum == 1) and (logStr.count('%') >= 1): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0]) except: logStr = "{str},{para1}".format(str=logStr, para1=num_list[0]) elif (logArgNum == 2) and (logStr.count('%') >= 2): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1]) except: logStr = "{str},{para1},{para2}".format(str=logStr, para1=num_list[0], para2=num_list[1]) elif (logArgNum == 3) and (logStr.count('%') >= 3): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2]) except: logStr = "{str},{para1},{para2},{para3}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2]) elif (logArgNum == 4) and (logStr.count('%') >= 4): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3]) except: logStr = "{str},{para1},{para2},{para3},{para4}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2], para4=num_list[3]) elif (logArgNum == 5) and (logStr.count('%') >= 5): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3], num_list[4]) except: logStr = "{str},{para1},{para2},{para3},{para4},{para5}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2], para4=num_list[3], para5=num_list[4]) elif (logArgNum == 6) and (logStr.count('%') >= 6): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3], num_list[4], num_list[5]) except: logStr = "{str},{para1},{para2},{para3},{para4},{para5},{para6}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2], para4=num_list[3], para5=num_list[4], para6=num_list[5]) log = "{time},{level},{module},{str}\n".format( time=time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(logTime)), level=g_logLevel[logLevel & 0x7F], module=g_logModule[logModule], str=logStr.replace(r'\t', '\t').replace(r'\'', "'")) logResultFile.write(log) logContentIndex = logContentIndex + 12 + logArgNum * 4 else: logContentIndex = self.find_head_index(logContent, logContentIndex) logResultFile.close() print("success") def find_head_index(self, logContent, index): # 该方法用于查找日志头部的起始索引。 firstFlag = logContent[index:].find(0xED) + index if firstFlag == -1: return -1 ipos = firstFlag for i in range(4): varnum = logContent[ipos + 3] log_len = 4 * varnum + 12 if log_len < 12 or log_len > 36: return self.find_head_index(logContent, ipos + 1) ipos += log_len if ipos >= len(logContent): return firstFlag if log_len == 12 and logContent[ipos] == 0 and logContent[ipos + 1] == 0 and logContent[ipos + 2] == 0 and logContent[ipos + 3] == 0: ipos += 4 if logContent[ipos] != 0xED: return self.find_head_index(logContent, ipos + 1) return firstFlag def isText(s): # 该函数用于判断字符串是否为文本。 if len(s) == 0: return False if not s: return False if (s.count('\\x') >= 1): return False return True def indexOfSubstr(logStr): # 该函数用于查找日志字符串中 % u的索引。 indexList = [] index = 0 for i in range(len(logStr)): if logStr[i:i+1] == '%': index = index + 1 para = logStr[i:i+2] if para == '%u': indexList.append(index) return indexList def GetBinString(binFile, logDict): with open(binFile, 'rb') as f: content = f.read() # 使用正则找到连续的 8 个 ASCII 字符以上的字符串 matches = re.finditer(rb'[\\x20-\\x7E]{8,}', content) for match in matches: address = match.start() text = match.group().decode('ascii', errors='ignore') text = text.replace('\r', '').replace('\n', '') text = text.replace('{public}', '').replace('{private}', '') text = text.replace('%ll', '%') text = text.replace('%p', '%x') # text = text.replace(r'\t', '\t').replace(r'\'', "'") # 在这里无效 stringAddress = f"{address:08X}" logDict[stringAddress] = f"{stringAddress} {text}" def GetBinFiles(root): gpu_log_str_bin = "" mcu_log_str_bin = "" bin_files = [] for file in os.listdir(root): path = os.path.join(root, file) if not os.path.isfile(path): continue lower_file = file.lower() if "gpu_log_str.bin" in lower_file: gpu_log_str_bin = path elif "mcu_log_str.bin" in lower_file: mcu_log_str_bin = path if file.endswith(".bin"): bin_files.append(path) return gpu_log_str_bin, mcu_log_str_bin, bin_files def CheckBinAddr(bin_infos, bin_files): # 该函数用于检查二进制文件的地址信息是否正确。 for info in bin_infos: if info.start_address != 4294967295: flag = True for i in bin_files: if info.flag == "application.bin": if info.flag in i or "OHOS_Image.bin" in i or "factory.bin" in i: flag = False info.bin_path = i elif info.flag in i: flag = False info.bin_path = i if flag: if info.flag == "application.bin": errorLog = "error info: need application.bin or OHOS_Image.bin or factory.bin" else: errorLog = "error info: need %s" % info.flag print("{str}".format(str=errorLog)) sys.exit(-1) def Addr(log_str_bin): # 该函数用于从二进制文件中获取地址信息。 with open(log_str_bin, mode="rb") as f: f.seek(0, 0) binAddr = f.read(32) strBinAddr = int.from_bytes(binAddr[4:8], "little") romBinAddr = int.from_bytes(binAddr[8:12], "little") xipBinAddr = int.from_bytes(binAddr[12:16], "little") itcmBinAddr = int.from_bytes(binAddr[16:20], "little") sramBinAddr = int.from_bytes(binAddr[20:24], "little") reveser1Addr = int.from_bytes(binAddr[24:28], "little") reveser2Addr = int.from_bytes(binAddr[28:32], "little") return strBinAddr, romBinAddr, xipBinAddr, itcmBinAddr, sramBinAddr, reveser1Addr, reveser2Addr def GetBinFilesString(bin_files): # 该函数用于获取二进制文件的内容和字符串信息。 for file in bin_files: if file.start_address != 4294967295: with open(file.bin_path, 'rb') as f: binFileSize = os.path.getsize(file.bin_path) f.seek(0, 0) file.bin_content = f.read(binFileSize) file.end_address = file.start_address + binFileSize GetBinString(file.bin_path, file.bin_dict) # def main(logFileArg1, root1): # global logFileArg # # logFileArg = logFileArg1 # global root # root = root1 # print(logFileArg) # # print(root) # # print("lex111111") # # os.system("pause") # # # # gpu_info = BIN_INFO("gpu_log_str.bin") # mcu_info = BIN_INFO("mcu_log_str.bin") # rom_info = BIN_INFO("application.bin") # xip_info = BIN_INFO("xip_code.bin") # itcm_info = BIN_INFO("itcm_code.bin") # sram_info = BIN_INFO("sram_code.bin") # reverse1_info = BIN_INFO("reserve1.bin") # reverse2_info = BIN_INFO("reserve2.bin") # print(xip_info) # # gpu_info.bin_path, mcu_info.bin_path, bin_files = GetBinFiles(root) # if logFileArg.endswith("gpu_debug.log"): # if gpu_info.bin_path == "": # errorLog = "error info: need gpu_log_str.bin" # print("{str}".format(str=errorLog)) # sys.exit(-1) # else: # gpu_info.start_address, rom_info.start_address, xip_info.start_address, itcm_info.start_address, sram_info.start_address, \ # reverse1_info.start_address, reverse2_info.start_address = GetBinAddr(gpu_info.bin_path) # bin_infos = [gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info] # CheckBinAddr(bin_infos, bin_files) # GetBinFilesString(bin_infos) # logProcessThread = LogProcessThread(log_file=logFileArg, # gpu_info=gpu_info, # rom_info=rom_info, # xip_info=xip_info, # itcm_info=itcm_info, # sram_info=sram_info, # reverse1_info=reverse1_info, # reverse2_info=reverse2_info, ) # logProcessThread.start_parse_v1r6() # elif logFileArg.endswith("mcu_debug.log"): # if mcu_info.bin_path == "": # errorLog = "error info: need mcu_log_str.bin" # print("{str}".format(str=errorLog)) # sys.exit(-1) # else: # mcu_info.start_address, rom_info.start_address, xip_info.start_address, itcm_info.start_address, sram_info.start_address, \ # reverse1_info.start_address, reverse2_info.start_address = GetBinAddr(mcu_info.bin_path) # bin_infos = [mcu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info] # CheckBinAddr(bin_infos, bin_files) # GetBinFilesString(bin_infos) # logProcessThread = LogProcessThread(log_file=logFileArg, # gpu_info=mcu_info, # rom_info=rom_info, # xip_info=xip_info, # itcm_info=itcm_info, # sram_info=sram_info, # reverse1_info=reverse1_info, # reverse2_info=reverse2_info, ) # logProcessThread.start_parse_v1r6() def main(logFileArg1=None, root1=None): """ 解析 GPU 日志主函数 :param logFileArg1: WearableBeta_gpu_debug.log 文件路径(可选) :param root1: bes2720_m33_user 等 bin 文件所在目录(可选) """ global logFileArg, root # === 自动查找 log 文件 === if logFileArg1 is None: temp_dir = getRelPath("temp_extracted") print(f" 正在搜索日志文件... 路径: {temp_dir}") found = False for root_path, dirs, files in os.walk(temp_dir): for file in files: if file.endswith("WearableBeta_gpu_debug.log"): # 只要结尾匹配即可 logFileArg1 = os.path.join(root_path, file) print(f" 找到日志文件: {logFileArg1}") found = True break if found: break if not found: print("❌ 错误:未找到 WearableBeta_gpu_debug.log,请检查 ZIP 是否解压成功") return # === 自动查找 bin 目录 === if root1 is None: version_cache = getRelPath("Version_cache") print(f"正在扫描 Version_cache: {version_cache}") found = False for root_path, dirs, files in os.walk(version_cache): if "bes2720_m33_user" in dirs: root1 = os.path.join(root_path, "bes2720_m33_user") print(f"成功定位 bes2720_m33_user: {root1}") # 新增:列出内容确认是否有 gpu_log_str.bin try: bin_files = os.listdir(root1) print(f"bes2720_m33_user 内容预览:") for f in sorted(bin_files): if f.endswith(".bin"): print(f" - {f}") except Exception as e: print(f"无法读取目录: {e}") found = True break if not found: print("错误:未找到 bes2720_m33_user 文件夹,请检查固件是否下载成功") return # === 设置全局变量(原逻辑保持不变)=== logFileArg = logFileArg1 root = root1 gpu_info = BIN_INFO("gpu_log_str.bin") mcu_info = BIN_INFO("mcu_log_str.bin") rom_info = BIN_INFO("application.bin") xip_info = BIN_INFO("xip_code.bin") itcm_info = BIN_INFO("itcm_code.bin") sram_info = BIN_INFO("sram_code.bin") reverse1_info = BIN_INFO("reserve1.bin") reverse2_info = BIN_INFO("reserve2.bin") gpu_info.bin_path, mcu_info.bin_path, bin_files = GetBinFiles(root) output_file = os.path.join(getRelPath("input"), "gpu_debug.log_offline.txt") os.makedirs(os.path.dirname(output_file), exist_ok=True) if "gpu_debug.log" in logFileArg: if not gpu_info.bin_path: print("❌ error info: need gpu_log_str.bin") return else: try: addr_list = GetBinAddr(gpu_info.bin_path) gpu_info.start_address, rom_info.start_address, xip_info.start_address, \ itcm_info.start_address, sram_info.start_address, reverse1_info.start_address, \ reverse2_info.start_address = addr_list except Exception as e: print(f"❌ 解析 Bin 地址失败: {e}") return bin_infos = [gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info] def CheckBinAddr(bin_infos, bin_files): """ 检查每个 BIN_INFO 是否能找到对应的 .bin 文件 支持:大小写不敏感、路径包含关键词即可、application.bin 可由 OHOS_Image/factory 替代 跳过:start_address == 4294967295 的项 """ for info in bin_infos: # 如果地址无效,说明该段未启用,直接跳过 if info.start_address == 4294967295 or info.start_address == 0: print(f" 跳过 {info.flag}:起始地址无效 (0x{info.start_address:X})") continue matched = False target_flag = info.flag.lower() base_names_included = [os.path.basename(f).lower() for f in bin_files] # 尝试匹配每一个可用的 .bin 文件 for path in bin_files: filename = os.path.basename(path).lower() # 特殊处理 application.bin:可用多个名称替代 if target_flag == "application.bin": if any(kw in filename for kw in ["application", "ohos_image", "factory"]): info.bin_path = path print(f" 使用 {filename} 匹配 {info.flag}") matched = True break # 通用规则:文件名包含 flag 关键词(如 xip_code.bin ← xip_code_xxx.bin) elif target_flag.replace(".bin", "") in filename: info.bin_path = path print(f" 使用 {filename} 匹配 {info.flag}") matched = True break # 完全没找到 → 报错退出 if not matched: print(f" 错误:找不到 {info.flag} 对应的文件") print(f" 需要一个包含 '{target_flag.replace('.bin', '')}' 的 .bin 文件") print(f" 当前可用文件: {[os.path.basename(f) for f in bin_files]}") if info.flag == "application.bin":print(" 提示:请提供 application.bin / OHOS_Image.bin / factory.bin") sys.exit(-1) # ======================== # 入口点:允许直接运行或被导入 # ======================== if __name__ == "__main__": # 如果命令行传参,则使用;否则自动查找 if len(sys.argv) == 3: main(sys.argv[1], sys.argv[2]) else: print("📌 未提供参数,进入自动模式...") main() # 自动查找路径
最新发布
12-18
这个代码是怎么处理的呢?这个代码只需要三个bin文件就可以跑通:gpu_log_str.bin、OHOS_Image.bin、xip_code.bin import os import subprocess import sys import time g_logLevel = ['INVALID', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'] # g_logLevel 是一个列表,定义了日志的级别。g_logModule 是一个字典,将模块的十六进制编号映射到模块名称 g_logModule = { 0x00 : 'HIVIEW', 0x01 : 'SAMGR', 0x02 : 'UPDATE', 0x03 : 'ACE', 0x04 : 'APP', 0x05 : 'AAFWK', 0x06 : 'GRAPHIC', 0x07 : 'MEDIA', 0x08 : 'DMA', 0x09 : 'SEN', 0x0A : 'SCY', 0x0B : 'XTS', 0x0C : 'SOFTBUS', 0x0D : 'PWM', 0x0E : 'UIKIT', 0x0F : 'GLOBAL', 0x10 : 'DATAMGR', 0x1E : 'HISI', 0x1F : 'COMMU', 0x20 : 'NV', 0x21 : 'BSP', 0x22 : 'DM', 0x23 : 'PM', 0x24 : 'LCD', 0x25 : 'GPS', 0x26 : 'BT', 0x27 : 'NFC', 0x28 : 'SVRAUDIO', 0x29 : 'FTM', 0x2A : 'SVR', 0x2B : 'APPUI', 0x2C : 'AST', 0x2D : 'FIT', 0x2E : 'ALG', 0x2F : 'HRM', 0x30 : 'TLV', 0x31 : 'WIFI', 0x32 : 'INPUT', 0x33 : 'RFID', 0x34 : 'EARSDK', 0x35 : 'SVCOMMU', 0x36 : 'RSMC', 0x37 : 'UWB', 0x38 : 'WATCHEAR', 0x39 : 'PAIR', 0x3A : 'DRVAUDIO', 0x3B : 'BRIGHT', 0x3C : 'FITUI', 0x3D : 'DIALUI', 0x3E : 'FMKUI', 0x3F : 'HRMUI' } class BIN_INFO(): # 该类用于存储二进制文件的相关信息,包括起始地址、结束地址、二进制内容、文件路径、内容字典和标志。 def __init__(self, flag): self.start_address = 0 self.end_address = 0 self.bin_content = [] self.bin_path = "" self.bin_dict = {} self.flag = flag class LogProcessThread(): # 该类用于处理日志文件,初始化时接收日志文件和各种二进制文件信息。 def __init__(self, log_file, gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info): self.log_file = log_file self.gpu_info = gpu_info self.rom_info = rom_info self.xip_info = xip_info self.itcm_info = itcm_info self.sram_info = sram_info self.reverse1_info = reverse1_info self.reverse2_info = reverse2_info def find_address_by_bin(self, logStr, key_index, num_list, bin_files_dict): # 该方法用于在二进制文件中查找地址对应的字符串,并替换日志字符串中的 % s占位符。 s_list = [] for i in range(len(logStr)): if logStr[i] == "%" and i != len(logStr) - 1: s_list.append(logStr[i: i + 2]) for i in range(len(s_list)): if s_list[i] == "%s": for j in key_index: if num_list[i] > j: address = num_list[i] - j new_s = "" if (bin_files_dict.get(j).bin_dict.__contains__(address) == False): new_s = str(bin_files_dict.get(j).bin_content[address:-1]).split('\\x00', 1)[0] new_s = new_s[2: len(new_s)] if isText(logStr): new_s = new_s.replace('\r', '') new_s = new_s.replace('\n', '') new_s = new_s.replace('{public}', '') new_s = new_s.replace('{private}', '') new_s = new_s.replace('%ll', '%') new_s = new_s.replace('%p', '%x') bin_files_dict.get(j).bin_dict[address] = new_s else: new_s = 'NULL' else: new_s = bin_files_dict.get(j).bin_dict[address] num_list[i] = new_s break return num_list def return_format_str(self, logStr, logContent, logContentIndex, num): # 该方法用于从日志内容中提取格式化字符串的参数。 num_list = [] index = logStr.find('%', 0, len(logStr)) temp_num = 0 while (index >= 0) or (temp_num < num): startLogIndex = logContentIndex + 12 + temp_num * 4 endLogIndex = logContentIndex + 12 + (temp_num + 1) * 4 if "%d" in logStr[index:index + 2]: logArgOne = int.from_bytes(logContent[startLogIndex:endLogIndex], "little", signed=True) num_list.append(logArgOne) else: logArgOne = int.from_bytes(logContent[startLogIndex:endLogIndex], "little", signed=False) num_list.append(logArgOne) index = logStr.find('%', index + 1, len(logStr)) temp_num += 1 return num_list def start_parse_v1r6(self): # 该方法是核心的日志解析方法,从日志文件中读取内容,检查日志的头部信息、级别、模块和参数数量,提取日志字符串和参数,格式化日志信息并写入结果文件。 with open(self.log_file, 'rb') as logFile: #logFile = open(self.log_file, 'rb') logFileSize = os.path.getsize(self.log_file) logFile.seek(0, 0) logContent = logFile.read(logFileSize) list1 = [self.gpu_info, self.rom_info, self.xip_info, self.itcm_info, self.sram_info, self.reverse1_info, self.reverse2_info] bin_files_dict = {} for i in list1: if i.start_address != 4294967295 and i.start_address != 0: bin_files_dict[i.start_address] = i key_index = sorted(bin_files_dict.keys(), reverse=True) logResultFile = open(logFileArg + '_offline.txt', 'w', encoding='utf8', errors='ignore') logContentIndex = self.find_head_index(logContent, 0) while logContentIndex <= logFileSize - 12: if logContent[logContentIndex] == 0xED: # check the log level is in range or not logLevel = logContent[logContentIndex + 1] if (logLevel & 0x7F) >= 0x06: logContentIndex = self.find_head_index(logContent, logContentIndex + 1) continue # check the log module is in range or not logModule = logContent[logContentIndex + 2] # if g_logModule.__contains__(logModule) == False: # logContentIndex = logContentIndex + 1 # continue # check the log arguments is larger than 6 or not logArgNum = logContent[logContentIndex + 3] if logArgNum > 6: logContentIndex = self.find_head_index(logContent, logContentIndex) continue logTime = int.from_bytes(logContent[logContentIndex + 4: logContentIndex + 8], "little") logAddress = int.from_bytes(logContent[logContentIndex + 8: logContentIndex + 12], "little") logStr = 'NULL' if logLevel < 0x06: for i in key_index: if logAddress > i: address = logAddress - i if (bin_files_dict.get(i).bin_dict.__contains__(address) == False): logStr = str(bin_files_dict.get(i).bin_content[address:-1]).split('\\x00', 1)[0] logStr = logStr[2: len(logStr)] if isText(logStr): logStr = logStr.replace('\\r', '') logStr = logStr.replace('\\n', '') logStr = logStr.replace('{public}', '') logStr = logStr.replace('{private}', '') logStr = logStr.replace('%ll', '%') logStr = logStr.replace('%p', '%x') bin_files_dict.get(i).bin_dict[address] = logStr else: logStr = 'NULL' else: logStr = bin_files_dict.get(i).bin_dict[address] break if (logArgNum == 1) and (logStr.count('%') >= 1): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0]) except: logStr = "{str},{para1}".format(str=logStr, para1=num_list[0]) elif (logArgNum == 2) and (logStr.count('%') >= 2): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1]) except: logStr = "{str},{para1},{para2}".format(str=logStr, para1=num_list[0], para2=num_list[1]) elif (logArgNum == 3) and (logStr.count('%') >= 3): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2]) except: logStr = "{str},{para1},{para2},{para3}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2]) elif (logArgNum == 4) and (logStr.count('%') >= 4): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3]) except: logStr = "{str},{para1},{para2},{para3},{para4}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2], para4=num_list[3]) elif (logArgNum == 5) and (logStr.count('%') >= 5): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3], num_list[4]) except: logStr = "{str},{para1},{para2},{para3},{para4},{para5}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2], para4=num_list[3], para5=num_list[4]) elif (logArgNum == 6) and (logStr.count('%') >= 6): num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum) if logStr.find('%s') != -1: num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict) try: logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3], num_list[4], num_list[5]) except: logStr = "{str},{para1},{para2},{para3},{para4},{para5},{para6}".format(str=logStr, para1=num_list[0], para2=num_list[1], para3=num_list[2], para4=num_list[3], para5=num_list[4], para6=num_list[5]) log = "{time},{level},{module},{str}\n".format( time=time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(logTime)), level=g_logLevel[logLevel & 0x7F], module=g_logModule[logModule], str=logStr) logResultFile.write(log) logContentIndex = logContentIndex + 12 + logArgNum * 4 else: logContentIndex = self.find_head_index(logContent, logContentIndex) logResultFile.close() print("success") def find_head_index(self, logContent, index): # 该方法用于查找日志头部的起始索引。 firstFlag = logContent[index:].find(0xED) + index if firstFlag == -1: return -1 ipos = firstFlag for i in range(4): varnum = logContent[ipos + 3] log_len = 4 * varnum + 12 if log_len < 12 or log_len > 36: return self.find_head_index(logContent, ipos + 1) ipos += log_len if ipos >= len(logContent): return firstFlag if log_len == 12 and logContent[ipos] == 0 and logContent[ipos + 1] == 0 and logContent[ipos + 2] == 0 and logContent[ipos + 3] == 0: ipos += 4 if logContent[ipos] != 0xED: return self.find_head_index(logContent, ipos + 1) return firstFlag def isText(s): # 该函数用于判断字符串是否为文本。 if len(s) == 0: return False if not s: return False if (s.count('\\x') >= 1): return False return True def indexOfSubstr(logStr): # 该函数用于查找日志字符串中 % u的索引。 indexList = [] index = 0 for i in range(len(logStr)): if logStr[i:i+1] == '%': index = index + 1 para = logStr[i:i+2] if para == '%u': indexList.append(index) return indexList def GetBinString(binFile, dict): # 该函数用于从二进制文件中提取字符串,并存储到字典中。 getStringsInBinCmd = "strings -n8 -td '%s'" % (binFile) stringsCmdOutPut = subprocess.check_output(getStringsInBinCmd, shell=True) stringsCmdOutPutText = stringsCmdOutPut.decode('utf-8') for subString in stringsCmdOutPutText.split('\n'): if len(subString) > 0: tempString = subString.lstrip() stringAddress = int(tempString.split(' ', 1)[0]) logContent = tempString.split(' ', 1)[1] logContent = logContent.replace('\r', '') logContent = logContent.replace('\n', '') logContent = logContent.replace('{public}', '') logContent = logContent.replace('{private}', '') logContent = logContent.replace('%ll', '%') logContent = logContent.replace('%p', '%x') dict[stringAddress] = logContent def GetBinFiles(root): # 该函数用于从指定目录中获取二进制文件列表。 gpu_log_str_bin = "" mcu_log_str_bin = "" bin_files = [] for file in os.listdir(root): if file.__contains__("gpu_log_str.bin"): gpu_log_str_bin = os.path.join(root, file) bin_files.append(os.path.join(root, file)) elif file.__contains__("mcu_log_str.bin"): mcu_log_str_bin = os.path.join(root, file) bin_files.append(os.path.join(root, file)) elif file[-4:] == ".bin": bin_files.append(os.path.join(root, file)) return gpu_log_str_bin, mcu_log_str_bin, bin_files def CheckBinAddr(bin_infos, bin_files): # 该函数用于检查二进制文件的地址信息是否正确。 for info in bin_infos: if info.start_address != 4294967295: flag = True for i in bin_files: if info.flag == "application.bin": if info.flag in i or "OHOS_Image.bin" in i or "factory.bin" in i: flag = False info.bin_path = i elif info.flag in i: flag = False info.bin_path = i if flag: if info.flag == "application.bin": errorLog = "error info: need application.bin or OHOS_Image.bin or factory.bin" else: errorLog = "error info: need %s" % info.flag print("{str}".format(str=errorLog)) sys.exit(-1) def GetBinAddr(log_str_bin): # 该函数用于从二进制文件中获取地址信息。 with open(log_str_bin, mode="rb") as f: f.seek(0, 0) binAddr = f.read(32) strBinAddr = int.from_bytes(binAddr[4:8], "little") romBinAddr = int.from_bytes(binAddr[8:12], "little") xipBinAddr = int.from_bytes(binAddr[12:16], "little") itcmBinAddr = int.from_bytes(binAddr[16:20], "little") sramBinAddr = int.from_bytes(binAddr[20:24], "little") reveser1Addr = int.from_bytes(binAddr[24:28], "little") reveser2Addr = int.from_bytes(binAddr[28:32], "little") return strBinAddr, romBinAddr, xipBinAddr, itcmBinAddr, sramBinAddr, reveser1Addr, reveser2Addr def GetBinFilesString(bin_files): # 该函数用于获取二进制文件的内容和字符串信息。 for file in bin_files: if file.start_address != 4294967295: with open(file.bin_path, 'rb') as f: binFileSize = os.path.getsize(file.bin_path) f.seek(0, 0) file.bin_content = f.read(binFileSize) file.end_address = file.start_address + binFileSize GetBinString(file.bin_path, file.bin_dict) if __name__ == '__main__': logFileArg = sys.argv[1] root = sys.argv[2] gpu_info = BIN_INFO("gpu_log_str.bin") mcu_info = BIN_INFO("mcu_log_str.bin") rom_info = BIN_INFO("application.bin") xip_info = BIN_INFO("xip_code.bin") itcm_info = BIN_INFO("itcm_code.bin") sram_info = BIN_INFO("sram_code.bin") reverse1_info = BIN_INFO("reserve1.bin") reverse2_info = BIN_INFO("reserve2.bin") gpu_info.bin_path, mcu_info.bin_path, bin_files = GetBinFiles(root) if logFileArg.endswith("gpu_debug.log"): if gpu_info.bin_path == "": errorLog = "error info: need gpu_log_str.bin" print("{str}".format(str=errorLog)) sys.exit(-1) else: gpu_info.start_address, rom_info.start_address, xip_info.start_address, itcm_info.start_address, sram_info.start_address, \ reverse1_info.start_address, reverse2_info.start_address = GetBinAddr(gpu_info.bin_path) bin_infos = [gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info] CheckBinAddr(bin_infos, bin_files) GetBinFilesString(bin_infos) logProcessThread = LogProcessThread(log_file=logFileArg, gpu_info=gpu_info, rom_info=rom_info, xip_info=xip_info, itcm_info=itcm_info, sram_info=sram_info, reverse1_info=reverse1_info, reverse2_info=reverse2_info, ) logProcessThread.start_parse_v1r6() elif logFileArg.endswith("mcu_debug.log"): if mcu_info.bin_path == "": errorLog = "error info: need mcu_log_str.bin" print("{str}".format(str=errorLog)) sys.exit(-1) else: mcu_info.start_address, rom_info.start_address, xip_info.start_address, itcm_info.start_address, sram_info.start_address, \ reverse1_info.start_address, reverse2_info.start_address = GetBinAddr(mcu_info.bin_path) bin_infos = [mcu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info] CheckBinAddr(bin_infos, bin_files) GetBinFilesString(bin_infos) logProcessThread = LogProcessThread(log_file=logFileArg, gpu_info=mcu_info, rom_info=rom_info, xip_info=xip_info, itcm_info=itcm_info, sram_info=sram_info, reverse1_info=reverse1_info, reverse2_info=reverse2_info, ) logProcessThread.start_parse_v1r6()
12-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值