13.正則表達式:文本處理的瑞士軍刀

正則表達式:文本處理的瑞士軍刀

🎯 前言:當文本遇上神奇的密碼

想象一下,你是一個圖書管理員,面對著一堆亂七八糟的書籍信息:

  • “聯系電話:138-1234-5678”
  • “郵箱地址:zhang.san@gmail.com”
  • “身份證號:110101199001011234”
  • “QQ號碼:12345678”

如果讓你一個個手工整理,估計你會瘋掉。但是,如果你掌握了正則表達式這把"瑞士軍刀",這些看似繁瑣的文本處理任務就會變得輕松愉快!

正則表達式(Regular Expression,簡稱 regex 或 regexp)就像是一種神奇的"文本搜索密碼",它能夠幫你在海量文本中精準定位你想要的內容。今天我們就來學習這門讓文本處理變得如絲般順滑的技藝!

📚 目錄

  • 什么是正則表達式
  • 基礎語法:學會寫"文本密碼"
  • Python中的正則表達式模塊
  • 實戰案例:從簡單到復雜
  • 高級技巧:讓你的正則更強大
  • 常見應用場景
  • 性能優化與最佳實踐

🧠 什么是正則表達式

生活中的"模式匹配"

在解釋正則表達式之前,我們先來看看生活中的例子。你有沒有這樣的經歷:

  • 在一堆照片中找出所有包含"生日"的文件名
  • 在通訊錄中找出所有138開頭的手機號
  • 在郵件中找出所有的網址鏈接

這些其實都是"模式匹配"的過程,而正則表達式就是用來描述這些"模式"的一種特殊語言。

正則表達式的本質

正則表達式本質上就是一個字符串,但這個字符串有特殊的含義——它描述了一種文本模式。比如:

  • \d{3}-\d{4}-\d{4} 描述了"3位數字-4位數字-4位數字"的模式
  • \w+@\w+\.\w+ 描述了基本的郵箱格式模式

📖 基礎語法:學會寫"文本密碼"

字符匹配:最基本的積木

import re# 直接匹配字符
text = "Hello World"
pattern = "Hello"
result = re.search(pattern, text)
print(result)  # <re.Match object; span=(0, 5), match='Hello'>

特殊字符:正則表達式的"魔法符號"

1. 點號(.):萬能替身
# . 可以匹配任意單個字符(除了換行符)
pattern = "H.llo"
text1 = "Hello"  # 匹配
text2 = "Hallo"  # 匹配
text3 = "H@llo"  # 匹配
text4 = "Hllo"   # 不匹配for text in [text1, text2, text3, text4]:if re.search(pattern, text):print(f"'{text}' 匹配成功!")else:print(f"'{text}' 匹配失敗!")
2. 星號(*):貪婪的小怪獸
# * 表示前面的字符可以出現0次或多次
pattern = "ab*c"
texts = ["ac", "abc", "abbc", "abbbc", "axc"]for text in texts:if re.search(pattern, text):print(f"'{text}' 匹配成功!")else:print(f"'{text}' 匹配失敗!")
3. 加號(+):至少要有一個
# + 表示前面的字符至少出現1次
pattern = "ab+c"
texts = ["ac", "abc", "abbc", "abbbc"]for text in texts:if re.search(pattern, text):print(f"'{text}' 匹配成功!")else:print(f"'{text}' 匹配失敗!")
4. 問號(?):可有可無的存在
# ? 表示前面的字符可以出現0次或1次
pattern = "colou?r"
texts = ["color", "colour", "colouur"]for text in texts:if re.search(pattern, text):print(f"'{text}' 匹配成功!")else:print(f"'{text}' 匹配失敗!")

字符類:給字符分分類

1. 方括號:自定義字符集合
# [abc] 匹配a、b、c中的任意一個
pattern = "[abc]at"
texts = ["cat", "bat", "rat", "hat"]for text in texts:if re.search(pattern, text):print(f"'{text}' 匹配成功!")else:print(f"'{text}' 匹配失敗!")
2. 范圍表示:偷個懶的寫法
# [a-z] 匹配任意小寫字母
# [0-9] 匹配任意數字
# [A-Za-z0-9] 匹配任意字母或數字pattern = "[0-9]+"  # 匹配一個或多個數字
text = "我今年25歲,電話是138-1234-5678"
numbers = re.findall(pattern, text)
print(numbers)  # ['25', '138', '1234', '5678']
3. 預定義字符類:常用的簡寫
# \d 等價于 [0-9]
# \w 等價于 [a-zA-Z0-9_]
# \s 等價于 [ \t\n\r\f\v](空白字符)text = "用戶名:zhang123,年齡:25歲"# 提取數字
numbers = re.findall(r'\d+', text)
print(f"數字:{numbers}")  # ['123', '25']# 提取單詞字符
words = re.findall(r'\w+', text)
print(f"單詞:{words}")  # ['zhang123', '25']

💻 Python中的正則表達式模塊

re模塊:Python的正則表達式工具箱

import re# 常用函數一覽
text = "今天是2024年1月1日,明天是2024年1月2日"# 1. re.search() - 找到第一個匹配
result = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', text)
if result:print(f"找到了:{result.group()}")  # 找到了:2024年1月1日# 2. re.findall() - 找到所有匹配
dates = re.findall(r'\d{4}年\d{1,2}月\d{1,2}日', text)
print(f"所有日期:{dates}")  # ['2024年1月1日', '2024年1月2日']# 3. re.sub() - 替換匹配的內容
new_text = re.sub(r'\d{4}年', '2025年', text)
print(f"替換后:{new_text}")  # 今天是2025年1月1日,明天是2025年1月2日# 4. re.split() - 按模式分割字符串
data = "蘋果,香蕉;橘子:葡萄"
fruits = re.split(r'[,:;]', data)
print(f"水果列表:{fruits}")  # ['蘋果', '香蕉', '橘子', '葡萄']

編譯正則表達式:提高效率的小技巧

# 如果同一個正則表達式要使用多次,可以先編譯
pattern = re.compile(r'\d{3}-\d{4}-\d{4}')phones = ["我的電話是138-1234-5678","客服熱線:400-1234-5678","傳真號碼:010-8888-9999","這不是電話號碼"
]for phone in phones:match = pattern.search(phone)if match:print(f"找到電話:{match.group()}")else:print("未找到電話號碼")

🚀 實戰案例:從簡單到復雜

案例1:驗證郵箱格式

def validate_email(email):"""驗證郵箱格式是否正確"""# 基礎版本basic_pattern = r'\w+@\w+\.\w+'# 進階版本(更嚴格)advanced_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'if re.match(advanced_pattern, email):return Truereturn False# 測試不同的郵箱
emails = ["zhangsan@gmail.com",      # 正確"li.si@163.com",           # 正確"wang@company.com.cn",     # 正確"invalid-email",           # 錯誤"@gmail.com",              # 錯誤"test@",                   # 錯誤
]for email in emails:result = "? 有效" if validate_email(email) else "? 無效"print(f"{email}: {result}")

案例2:提取網頁中的鏈接

def extract_links(html_content):"""從HTML內容中提取所有鏈接"""# 匹配 <a href="..."> 標簽中的鏈接pattern = r'<a\s+href=["\'](.*?)["\']'links = re.findall(pattern, html_content, re.IGNORECASE)return links# 示例HTML內容
html = '''
<html>
<body><a href="https://www.python.org">Python官網</a><a href="mailto:admin@example.com">聯系我們</a><a href="/about">關于我們</a><a HREF='https://github.com'>GitHub</a>
</body>
</html>
'''links = extract_links(html)
print("提取到的鏈接:")
for i, link in enumerate(links, 1):print(f"{i}. {link}")

案例3:解析日志文件

def parse_log_file(log_content):"""解析服務器日志文件"""# 典型的Apache日志格式# 127.0.0.1 - - [25/Dec/2023:10:00:00 +0000] "GET /index.html HTTP/1.1" 200 1234pattern = r'(\d+\.\d+\.\d+\.\d+).*?\[(.*?)\].*?"(\w+)\s+(.*?)\s+HTTP.*?"\s+(\d+)\s+(\d+)'matches = re.findall(pattern, log_content)logs = []for match in matches:ip, timestamp, method, url, status, size = matchlogs.append({'ip': ip,'timestamp': timestamp,'method': method,'url': url,'status': int(status),'size': int(size)})return logs# 示例日志內容
log_content = '''
127.0.0.1 - - [25/Dec/2023:10:00:00 +0000] "GET /index.html HTTP/1.1" 200 1234
192.168.1.1 - - [25/Dec/2023:10:05:00 +0000] "POST /login HTTP/1.1" 302 0
10.0.0.1 - - [25/Dec/2023:10:10:00 +0000] "GET /api/users HTTP/1.1" 404 567
'''logs = parse_log_file(log_content)
print("解析到的日志:")
for log in logs:print(f"IP: {log['ip']}, 狀態: {log['status']}, URL: {log['url']}")

案例4:數據清洗與格式化

def clean_phone_numbers(text):"""清洗和格式化電話號碼"""# 匹配各種格式的電話號碼patterns = [r'(\d{3})-(\d{4})-(\d{4})',      # 138-1234-5678r'(\d{3})\s+(\d{4})\s+(\d{4})',  # 138 1234 5678r'(\d{3})\.(\d{4})\.(\d{4})',    # 138.1234.5678r'(\d{11})',                     # 13812345678]def format_phone(match):if len(match.groups()) == 3:return f"{match.group(1)}-{match.group(2)}-{match.group(3)}"else:# 對于11位連續數字,分割為3-4-4格式phone = match.group(1)return f"{phone[:3]}-{phone[3:7]}-{phone[7:]}"result = textfor pattern in patterns:result = re.sub(pattern, format_phone, result)return result# 測試數據
messy_text = '''
聯系方式:
張三:138 1234 5678
李四:139.5678.9012
王五:13687654321
趙六:158-7890-1234
'''cleaned_text = clean_phone_numbers(messy_text)
print("清洗后的文本:")
print(cleaned_text)

🔧 高級技巧:讓你的正則更強大

1. 分組捕獲:抓住重要信息

# 使用括號創建捕獲組
pattern = r'(\d{4})-(\d{2})-(\d{2})'
text = "今天是2024-01-15,明天是2024-01-16"for match in re.finditer(pattern, text):print(f"完整匹配:{match.group(0)}")print(f"年份:{match.group(1)}")print(f"月份:{match.group(2)}")print(f"日期:{match.group(3)}")print("---")

2. 命名捕獲組:給組起個名字

# 使用 (?P<name>pattern) 創建命名組
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
text = "生日:1990-05-20"match = re.search(pattern, text)
if match:print(f"年份:{match.group('year')}")print(f"月份:{match.group('month')}")print(f"日期:{match.group('day')}")# 也可以用字典的方式訪問date_dict = match.groupdict()print(f"日期字典:{date_dict}")

3. 非捕獲組:只匹配不捕獲

# 使用 (?:pattern) 創建非捕獲組
pattern = r'(?:Mr|Mrs|Ms)\.\s+(\w+)'
text = "Mr. Smith 和 Mrs. Johnson 來了"matches = re.findall(pattern, text)
print(f"姓名:{matches}")  # ['Smith', 'Johnson']

4. 前瞻和后瞻:偷看前后的內容

# 正向前瞻 (?=pattern)
pattern = r'\d+(?=元)'  # 匹配后面跟著"元"的數字
text = "價格是100元,重量是50公斤"
prices = re.findall(pattern, text)
print(f"價格:{prices}")  # ['100']# 負向前瞻 (?!pattern)
pattern = r'\d+(?!元)'  # 匹配后面不跟著"元"的數字
weights = re.findall(pattern, text)
print(f"非價格數字:{weights}")  # ['50']

5. 貪婪與非貪婪匹配

text = '<div>內容1</div><div>內容2</div>'# 貪婪匹配(默認)
greedy_pattern = r'<div>.*</div>'
greedy_match = re.search(greedy_pattern, text)
print(f"貪婪匹配:{greedy_match.group()}")
# 結果:<div>內容1</div><div>內容2</div># 非貪婪匹配
non_greedy_pattern = r'<div>.*?</div>'
non_greedy_matches = re.findall(non_greedy_pattern, text)
print(f"非貪婪匹配:{non_greedy_matches}")
# 結果:['<div>內容1</div>', '<div>內容2</div>']

🎯 常見應用場景

1. 數據驗證工具箱

class DataValidator:"""數據驗證工具類"""@staticmethoddef validate_phone(phone):"""驗證手機號碼"""pattern = r'^1[3-9]\d{9}$'return bool(re.match(pattern, phone))@staticmethoddef validate_id_card(id_card):"""驗證身份證號碼"""pattern = r'^\d{17}[\dXx]$'return bool(re.match(pattern, id_card))@staticmethoddef validate_password(password):"""驗證密碼強度(至少8位,包含字母和數字)"""pattern = r'^(?=.*[a-zA-Z])(?=.*\d).{8,}$'return bool(re.match(pattern, password))@staticmethoddef validate_url(url):"""驗證URL格式"""pattern = r'^https?://[^\s/$.?#].[^\s]*$'return bool(re.match(pattern, url))# 測試驗證器
validator = DataValidator()test_data = {"手機號": "13812345678","身份證": "110101199001011234","密碼": "password123","網址": "https://www.example.com"
}for data_type, value in test_data.items():if data_type == "手機號":result = validator.validate_phone(value)elif data_type == "身份證":result = validator.validate_id_card(value)elif data_type == "密碼":result = validator.validate_password(value)elif data_type == "網址":result = validator.validate_url(value)status = "? 有效" if result else "? 無效"print(f"{data_type} {value}: {status}")

2. 文本信息提取器

class TextExtractor:"""文本信息提取器"""def __init__(self):self.patterns = {'email': r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b','phone': r'1[3-9]\d{9}','url': r'https?://[^\s]+','date': r'\d{4}[-/]\d{1,2}[-/]\d{1,2}','money': r'¥?\d+(?:\.\d{2})?','qq': r'[1-9]\d{4,11}','ip': r'\b(?:\d{1,3}\.){3}\d{1,3}\b'}def extract_all(self, text):"""提取文本中的所有信息"""results = {}for info_type, pattern in self.patterns.items():matches = re.findall(pattern, text)if matches:results[info_type] = matchesreturn results# 示例文本
sample_text = '''
個人信息:
姓名:張三
電話:13812345678
郵箱:zhangsan@gmail.com
QQ:123456789
生日:1990-05-20
網站:https://www.example.com
IP地址:192.168.1.1
余額:¥1234.56
'''extractor = TextExtractor()
extracted_info = extractor.extract_all(sample_text)print("提取到的信息:")
for info_type, values in extracted_info.items():print(f"{info_type}: {values}")

3. 日志分析工具

class LogAnalyzer:"""日志分析工具"""def __init__(self):# 定義不同類型的日志格式self.log_patterns = {'apache': r'(\d+\.\d+\.\d+\.\d+).*?\[(.*?)\].*?"(\w+)\s+(.*?)\s+HTTP.*?"\s+(\d+)\s+(\d+)','nginx': r'(\d+\.\d+\.\d+\.\d+).*?\[(.*?)\].*?"(\w+)\s+(.*?)\s+HTTP.*?"\s+(\d+)\s+(\d+)','error': r'\[(.*?)\]\s+\[(\w+)\]\s+(.*)','python': r'(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}),\d+\s+(\w+)\s+(.*)'}def analyze_access_log(self, log_content):"""分析訪問日志"""pattern = self.log_patterns['apache']matches = re.findall(pattern, log_content)analysis = {'total_requests': len(matches),'unique_ips': set(),'status_codes': {},'popular_pages': {},'methods': {}}for match in matches:ip, timestamp, method, url, status, size = matchanalysis['unique_ips'].add(ip)# 統計狀態碼if status in analysis['status_codes']:analysis['status_codes'][status] += 1else:analysis['status_codes'][status] = 1# 統計熱門頁面if url in analysis['popular_pages']:analysis['popular_pages'][url] += 1else:analysis['popular_pages'][url] = 1# 統計請求方法if method in analysis['methods']:analysis['methods'][method] += 1else:analysis['methods'][method] = 1analysis['unique_ips'] = len(analysis['unique_ips'])return analysis# 示例日志分析
log_content = '''
127.0.0.1 - - [25/Dec/2023:10:00:00 +0000] "GET /index.html HTTP/1.1" 200 1234
192.168.1.1 - - [25/Dec/2023:10:05:00 +0000] "POST /login HTTP/1.1" 302 0
10.0.0.1 - - [25/Dec/2023:10:10:00 +0000] "GET /api/users HTTP/1.1" 404 567
127.0.0.1 - - [25/Dec/2023:10:15:00 +0000] "GET /about HTTP/1.1" 200 890
'''analyzer = LogAnalyzer()
analysis = analyzer.analyze_access_log(log_content)print("日志分析結果:")
print(f"總請求數:{analysis['total_requests']}")
print(f"唯一IP數:{analysis['unique_ips']}")
print(f"狀態碼分布:{analysis['status_codes']}")
print(f"熱門頁面:{analysis['popular_pages']}")
print(f"請求方法:{analysis['methods']}")

? 性能優化與最佳實踐

1. 編譯正則表達式

import re
import time# 測試編譯與不編譯的性能差異
text = "這是一個測試文本,包含很多數字:12345,67890,13579,24680" * 1000def test_without_compile():"""不編譯正則表達式"""start_time = time.time()for _ in range(1000):re.findall(r'\d+', text)end_time = time.time()return end_time - start_timedef test_with_compile():"""編譯正則表達式"""pattern = re.compile(r'\d+')start_time = time.time()for _ in range(1000):pattern.findall(text)end_time = time.time()return end_time - start_timeprint(f"不編譯耗時:{test_without_compile():.4f}秒")
print(f"編譯后耗時:{test_with_compile():.4f}秒")

2. 避免回溯問題

# 不好的正則表達式(可能導致回溯)
bad_pattern = r'(a+)+b'# 好的正則表達式
good_pattern = r'a+b'# 測試文本(會導致回溯問題)
problematic_text = 'a' * 20# 建議:使用具體的量詞而不是嵌套的量詞

3. 使用正確的函數

text = "Hello World! This is a test."# 如果只需要知道是否匹配,使用 re.search()
if re.search(r'test', text):print("找到了 'test'")# 如果需要所有匹配,使用 re.findall()
words = re.findall(r'\w+', text)
print(f"所有單詞:{words}")# 如果需要替換,使用 re.sub()
new_text = re.sub(r'test', 'example', text)
print(f"替換后:{new_text}")

🔧 常見問題與解決方案

問題1:特殊字符需要轉義

# 錯誤:直接使用特殊字符
# pattern = r'$100'  # $ 是特殊字符,表示行尾# 正確:使用轉義字符
pattern = r'\$100'  # 正確匹配 "$100"
text = "價格是$100"
result = re.search(pattern, text)
print(result.group() if result else "未找到")

問題2:中文字符處理

# 匹配中文字符
chinese_pattern = r'[\u4e00-\u9fff]+'
text = "Hello 世界!今天天氣真好。"
chinese_words = re.findall(chinese_pattern, text)
print(f"中文內容:{chinese_words}")  # ['世界', '今天天氣真好']

問題3:多行文本處理

multiline_text = '''第一行
第二行
第三行'''# 默認情況下,. 不匹配換行符
pattern1 = r'第一行.*第三行'
result1 = re.search(pattern1, multiline_text)
print(f"默認模式:{result1}")  # None# 使用 re.DOTALL 標志讓 . 匹配換行符
pattern2 = r'第一行.*第三行'
result2 = re.search(pattern2, multiline_text, re.DOTALL)
print(f"DOTALL模式:{result2.group() if result2 else None}")

📖 擴展閱讀

推薦資源

  • 在線正則表達式測試工具:regex101.com
  • Python re模塊官方文檔:docs.python.org/3/library/re.html
  • 正則表達式教程:regexone.com
  • 《正則表達式必知必會》:經典的正則表達式入門書籍

實用工具

# 正則表達式調試器
def regex_debugger(pattern, text):"""正則表達式調試器"""try:compiled = re.compile(pattern)matches = compiled.findall(text)print(f"模式:{pattern}")print(f"文本:{text}")print(f"匹配結果:{matches}")print(f"匹配數量:{len(matches)}")except re.error as e:print(f"正則表達式語法錯誤:{e}")# 使用示例
regex_debugger(r'\d+', '我有123個蘋果和456個橘子')

🎬 下集預告

在下一篇文章《多線程與并發:讓程序同時做多件事》中,我們將探索:

  • 如何讓Python程序同時處理多個任務
  • 線程和進程的區別和使用場景
  • 異步編程的魅力
  • 并發編程的陷阱和最佳實踐

想象一下,如果你的程序能夠同時下載文件、處理數據、響應用戶請求,那該多么高效!

📝 總結與思考題

核心要點回顧

  1. 正則表達式是處理文本的強大工具,就像文本處理的"瑞士軍刀"
  2. 基礎語法包括字符匹配、量詞、字符類等
  3. Python的re模塊提供了豐富的函數來使用正則表達式
  4. 實際應用包括數據驗證、信息提取、日志分析等
  5. 性能優化通過編譯正則表達式和選擇合適的函數

實踐作業

  1. 寫一個函數,從一段文本中提取所有的IP地址
  2. 創建一個密碼強度檢查器,要求包含大小寫字母、數字和特殊字符
  3. 解析一個CSV格式的字符串,提取每一列的數據
  4. 編寫一個簡單的模板引擎,用正則表達式替換模板中的變量

思考題

  1. 為什么說正則表達式是"寫時簡單,讀時困難"?如何提高正則表達式的可讀性?
  2. 在什么情況下應該使用正則表達式,什么情況下應該使用字符串的普通方法?
  3. 如何平衡正則表達式的功能性和性能?

記住:正則表達式雖然強大,但也要適度使用。正如一句名言所說:"如果你有一個問題,想用正則表達式解決,那么你就有兩個問題了。"但是,如果你真正掌握了正則表達式,它就會成為你文本處理的得力助手!

🎉 恭喜你!你已經掌握了正則表達式這把文本處理的"瑞士軍刀"。現在你可以輕松地在茫茫文本海洋中找到你需要的信息,就像擁有了一雙火眼金睛!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91427.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91427.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91427.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux下c語言訪問mysql數據庫

一、連接數據庫基礎1. 頭文件與庫文件連接 MySQL 需包含的頭文件&#xff1a;#include <mysql/mysql.h> // 部分環境也可用 #include <mysql.h> 編譯鏈接時&#xff0c;Linux 平臺需指定庫名&#xff1a;-lmysqlclient &#xff0c;用于鏈接 MySQL 客戶端函數庫。2…

6. 傳輸層協議 UDP

傳輸層負責數據能夠從發送端傳輸接收端.1. 再談端口號端口號(Port)標識了一個主機上進行通信的不同的應用程序在 TCP/IP 協議中, 用 "源 IP", "源端口號", "目的 IP", "目的端口號", "協議號" 這樣一個五元組來標識一個通信…

vue 開發總結:從安裝到第一個交互頁面-與數據庫API

vue 總結 1、安裝vue&#xff1a; WinR 輸入&#xff1a;cnpm install -g vue/cli 驗證是否安裝成功&#xff1a;vue --version 2、新建Vue工程 在對應文件夾下右擊打開集成終端 輸入 vue create query_system&#xff08;新建項目名字&#xff09;名稱不能存在大寫&#x…

運維筆記:HTTP 性能優化

一、HTTP 協議特性與性能瓶頸1.1 HTTP 協議發展歷程HTTP 協議的演進直接影響著 Web 性能&#xff0c;各版本關鍵特性對比&#xff1a;協議版本發布時間核心特性性能優勢局限性HTTP/1.01996 年無狀態、短連接簡單易實現每次請求需建立 TCP 連接HTTP/1.11999 年長連接、管道化減少…

ubuntu:運行gcfsd-admin守護進程需要認證,解決方法

這里有個鎖子&#xff0c;每次進入都要輸入密碼&#xff0c;怎么解決&#xff1f; 重新掛載 /data 磁盤 sudo umount /data sudo ntfsfix /dev/sda1 sudo mount -o rw /dev/sda1 /data

1.DRF 環境安裝與配置

文章目錄一. Django Rest_Framework二、環境安裝與配置2.1 安裝 DRF2.2 創建Django項目2.3 添加 rest_framework 應用三、啟動項目一. Django Rest_Framework 核心思想&#xff1a;大量縮減編寫 api 接口的代碼 Django REST framework 是一個建立在 Django 基礎之上的 Web 應…

設計模式(十九)行為型:備忘錄模式詳解

設計模式&#xff08;十九&#xff09;行為型&#xff1a;備忘錄模式詳解備忘錄模式&#xff08;Memento Pattern&#xff09;是 GoF 23 種設計模式中的行為型模式之一&#xff0c;其核心價值在于在不破壞封裝性的前提下&#xff0c;捕獲并外部化一個對象的內部狀態&#xff0c…

Qt/C++開發監控GB28181系統/錄像回放/切換播放進度立即跳轉/支持8倍速播放/倍速和跳轉進度無縫切換

一、前言說明 在國標監控系統中&#xff0c;錄像回放過程中&#xff0c;需要切換播放進度&#xff0c;對比過很過國標系統&#xff0c;絕大部分尤其是網頁版的監控系統&#xff0c;在切換進度過程中都會黑屏&#xff0c;這個體驗就很不友好了&#xff0c;明明gb28181協議中就有…

【11】大恒相機SDK C++開發 ——原圖像數據IFrameData內存中上下顛倒,怎么裁剪ROI 實時顯示在pictureBox中

文章目錄3 當內存中的 圖像數據是垂直翻轉的時候怎么截取ROI 并顯示3.1 對ROI在原圖中的位置做轉換3.2 將ROI的最后一行當做開始位置&#xff0c;從底部向上復制數據3.3 完整代碼3.4 圖像數據在內存中上下顛倒的情況3.5 調用驗證4 unsafe代碼 解釋及注意事項 看我另一篇文章5 C…

小架構step系列29:校驗注解的組合

1 概述如果遇到某些屬性需要多種校驗&#xff0c;比如需要非空、符合某正則表達式、長度不能超過某值等&#xff0c;如果這種屬性只有有限幾個&#xff0c;那么手工把對應的校驗注解都加上即可。但如果這種屬性比較多&#xff0c;那么重復加這些校驗注解&#xff0c;也是一種代…

網絡基礎19:OSPF多區域實驗

一、拓撲結構1. 網絡拓撲&#xff1a;骨干區域&#xff08;Area 0&#xff09;&#xff1a;連接核心設備&#xff08;AR1、AR2、AR3、AR4、AR5、AR6&#xff09;。非骨干區域&#xff1a;Area 1&#xff1a;AR5 ? AR9Area 2&#xff1a;AR5 ? AR10Area 3&#xff1a;AR6 ? A…

goland編寫go語言導入自定義包出現: package xxx is not in GOROOT (/xxx/xxx) 的解決方案

問題 寫了個自定義的包 calc.go&#xff0c;在路徑 $GOPATH/go_project/src/demo_51_package/com/目錄下&#xff0c;其中main.go 是main方法的入口代碼 main.go 代碼如下 package main import "demo_51_package/com" func main() {add : calc.Add(1, 2)println(add)…

HLS視頻切片音頻中斷問題分析與解決方案

HLS視頻切片音頻中斷問題分析與解決方案 問題背景 在使用FFmpeg進行HLS視頻切片并通過hls.js前端播放時&#xff0c;開發者經常遇到一個典型問題&#xff1a;第一個視頻切片播放正常且有聲音&#xff0c;但后續切片卻突然失去音頻。這種現象在直播和點播場景中均有出現&#xf…

【Linux網絡編程】網絡層協議 - IP

目錄 背景補充 協議頭格式 IP報文的分片與組裝 網段劃分 網段劃分是什么&#xff1f;為什么要進行網段劃分&#xff1f; 怎么進行網段劃分&#xff1f; 路由 路由表生成算法 背景補充 假設現在主機B要給主機C發送消息。在我們前面的學習中&#xff0c;一直都是將數據拷…

從“救火”到“先知”:潤建曲尺運維大模型如何重構網絡運維價值鏈

“7月18號&#xff0c;北京&#xff0c;晴&#xff0c;最高溫度38攝氏度。”天氣預報緩緩播報&#xff0c;商場、地鐵、辦公樓無不歌頌著威利斯開利的貢獻&#xff0c;但這份涼爽的背后&#xff0c;離不開 “電” 的無聲托舉。5G毫秒級下載、絲滑的移動支付、智能電表、智能家居…

Element表格單元格類名動態設置

在 Element UI 的 el-table 組件中&#xff0c;cell-class-name 屬性用于動態自定義表格單元格的 CSS 類名&#xff0c;通常用于根據數據條件設置樣式。1. 基本用法在 el-table 上綁定 :cell-class-name 屬性&#xff0c;值為一個函數。該函數接收一個對象參數&#xff0c;返回…

利用容器適配器實現stack和queue外加deque的介紹(STL)

文章目錄前言什么是容器適配器&#xff1f;觀察庫中的源碼那么該如何使用容器適配器呢&#xff1f;deque的簡單介紹(了解)deque的原理介紹deque的優缺為什么選擇deque作為stack和queue的底層默認容器&#xff1f;&#xff08;重點&#xff09;利用容器適配器實現我們自己的棧和…

【因子動物園巡禮】第12章:機器學習在因子投資中的應用(中文翻譯)

【因子動物園巡禮】第12章&#xff1a;機器學習在因子投資中的應用&#xff08;中文翻譯&#xff09;第12章 因子投資中的機器學習12.1 量化金融中的人工智能12.2 量化因子投資的AI化組件&#xff1a;解剖學視角12.2.1 數據源拓展與預處理12.2.2 因子研究12.2.3 因子模型12.2.4…

【Golang】用官方rate包構造簡單IP限流器

文章目錄使用 Go 實現基于 IP 地址的限流機制什么是 IP 限流&#xff1f;基于 rate.Limiter 實現 IP 限流1. 設計思路2. 代碼實現3. 限流中間件4. 在 Gin 中使用中間件代碼解釋使用 Go 實現基于 IP 地址的限流機制 在高流量的服務中&#xff0c;限流是一個至關重要的環節。它不…

力扣 Pandas 挑戰(6)---數據合并

本文圍繞力扣的Pandas簡單題集&#xff0c;解析如何用Pandas完成基礎數據處理任務&#xff0c;適合Pandas初學者學習。題目1&#xff1a;1050. 合作過至少三次的演員和導演題目描述&#xff1a;ActorDirector 表&#xff1a;---------------------- | Column Name | Type | …