352 lines
8.2 KiB
Python
352 lines
8.2 KiB
Python
|
#!/usr/bin/env python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
|
|||
|
"""
|
|||
|
字符串工具函数
|
|||
|
提供各种字符串操作的实用函数
|
|||
|
所有函数均为异步实现
|
|||
|
"""
|
|||
|
|
|||
|
import re
|
|||
|
from typing import List, Optional, Union
|
|||
|
|
|||
|
|
|||
|
async def is_blank(s: Optional[str]) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否为None、空字符串或只包含空白字符
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串为None、空字符串或只包含空白字符,则返回True;否则返回False
|
|||
|
"""
|
|||
|
return s is None or (isinstance(s, str) and s.strip() == "")
|
|||
|
|
|||
|
|
|||
|
async def is_not_blank(s: Optional[str]) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否不为空(不为None且不只包含空白字符)
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串不为None且不只包含空白字符,则返回True;否则返回False
|
|||
|
"""
|
|||
|
return not await is_blank(s)
|
|||
|
|
|||
|
|
|||
|
async def is_any_blank(*strings: Optional[str]) -> bool:
|
|||
|
"""
|
|||
|
检查是否有任何一个字符串为空
|
|||
|
|
|||
|
Args:
|
|||
|
*strings: 要检查的字符串列表
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果任何一个字符串为空,则返回True;否则返回False
|
|||
|
"""
|
|||
|
for s in strings:
|
|||
|
if await is_blank(s):
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
|
|||
|
async def is_all_blank(*strings: Optional[str]) -> bool:
|
|||
|
"""
|
|||
|
检查是否所有字符串都为空
|
|||
|
|
|||
|
Args:
|
|||
|
*strings: 要检查的字符串列表
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果所有字符串都为空,则返回True;否则返回False
|
|||
|
"""
|
|||
|
for s in strings:
|
|||
|
if not await is_blank(s):
|
|||
|
return False
|
|||
|
return True
|
|||
|
|
|||
|
|
|||
|
async def is_numeric(s: Optional[str]) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否为数字(整数或浮点数)
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串是数字,则返回True;否则返回False
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return False
|
|||
|
try:
|
|||
|
float(s)
|
|||
|
return True
|
|||
|
except (ValueError, TypeError):
|
|||
|
return False
|
|||
|
|
|||
|
|
|||
|
async def is_alpha(s: Optional[str]) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否只包含字母
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串只包含字母,则返回True;否则返回False
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return False
|
|||
|
return isinstance(s, str) and s.isalpha()
|
|||
|
|
|||
|
|
|||
|
async def starts_with(s: Optional[str], prefix: str) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否以指定前缀开头
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
prefix: 前缀字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串以指定前缀开头,则返回True;否则返回False
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return False
|
|||
|
return isinstance(s, str) and s.startswith(prefix)
|
|||
|
|
|||
|
|
|||
|
async def ends_with(s: Optional[str], suffix: str) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否以指定后缀结尾
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
suffix: 后缀字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串以指定后缀结尾,则返回True;否则返回False
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return False
|
|||
|
return isinstance(s, str) and s.endswith(suffix)
|
|||
|
|
|||
|
|
|||
|
async def contains(s: Optional[str], sub: str) -> bool:
|
|||
|
"""
|
|||
|
检查字符串是否包含指定子字符串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要检查的字符串
|
|||
|
sub: 子字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
bool: 如果字符串包含指定子字符串,则返回True;否则返回False
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return False
|
|||
|
return isinstance(s, str) and sub in s
|
|||
|
|
|||
|
|
|||
|
async def split(s: Optional[str], sep: str, maxsplit: int = -1) -> List[str]:
|
|||
|
"""
|
|||
|
按指定分隔符拆分字符串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要拆分的字符串
|
|||
|
sep: 分隔符
|
|||
|
maxsplit: 最大拆分次数,默认为-1(无限制)
|
|||
|
|
|||
|
Returns:
|
|||
|
List[str]: 拆分后的字符串列表
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return []
|
|||
|
return s.split(sep, maxsplit)
|
|||
|
|
|||
|
|
|||
|
async def chop(s: Optional[str]) -> str:
|
|||
|
"""
|
|||
|
去掉字符串的最后一个字符
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要处理的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 处理后的字符串,如果原字符串为空,则返回空字符串
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return ""
|
|||
|
return s[:-1]
|
|||
|
|
|||
|
|
|||
|
async def chomp(s: Optional[str]) -> str:
|
|||
|
"""
|
|||
|
去掉字符串末尾的换行符(\\n、\\r 或 \\r\\n)
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要处理的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 处理后的字符串,如果原字符串为空,则返回空字符串
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return ""
|
|||
|
if s.endswith("\r\n"):
|
|||
|
return s[:-2]
|
|||
|
if s.endswith("\n") or s.endswith("\r"):
|
|||
|
return s[:-1]
|
|||
|
return s
|
|||
|
|
|||
|
|
|||
|
async def index_of(s: Optional[str], sub: str, start: int = 0, end: Optional[int] = None) -> int:
|
|||
|
"""
|
|||
|
查找子字符串在字符串中的索引位置
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要搜索的字符串
|
|||
|
sub: 要查找的子字符串
|
|||
|
start: 开始搜索的位置,默认为0
|
|||
|
end: 结束搜索的位置,默认为None(搜索到字符串末尾)
|
|||
|
|
|||
|
Returns:
|
|||
|
int: 子字符串在字符串中的索引位置,如果找不到则返回-1
|
|||
|
"""
|
|||
|
if await is_blank(s) or await is_blank(sub):
|
|||
|
return -1
|
|||
|
try:
|
|||
|
return s.index(sub, start, end) if end else s.index(sub, start)
|
|||
|
except ValueError:
|
|||
|
return -1
|
|||
|
|
|||
|
|
|||
|
async def difference(str1: Optional[str], str2: Optional[str]) -> str:
|
|||
|
"""
|
|||
|
获取第二个字符串在第一个字符串中不一样的部分
|
|||
|
从第二个字符串第一位去匹配第一个字符串,按照顺序比较
|
|||
|
|
|||
|
Args:
|
|||
|
str1: 第一个字符串
|
|||
|
str2: 第二个字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 不一样的部分,如果任一字符串为空或无差异,则返回空字符串
|
|||
|
"""
|
|||
|
if await is_blank(str1) or await is_blank(str2):
|
|||
|
return ""
|
|||
|
|
|||
|
# 找到共同前缀的长度
|
|||
|
i = 0
|
|||
|
min_len = min(len(str1), len(str2))
|
|||
|
while i < min_len and str1[i] == str2[i]:
|
|||
|
i += 1
|
|||
|
|
|||
|
# 如果第二个字符串比第一个短,或者完全匹配,则返回空字符串
|
|||
|
if i >= len(str2):
|
|||
|
return ""
|
|||
|
|
|||
|
# 返回不同的部分
|
|||
|
return str2[i:]
|
|||
|
|
|||
|
|
|||
|
async def replace(s: Optional[str], old: str, new: str, count: int = -1) -> str:
|
|||
|
"""
|
|||
|
替换字符串中的指定子串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 原字符串
|
|||
|
old: 要替换的子串
|
|||
|
new: 替换后的子串
|
|||
|
count: 替换次数,默认为-1(全部替换)
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 替换后的字符串
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return ""
|
|||
|
return s.replace(old, new, count)
|
|||
|
|
|||
|
|
|||
|
async def remove(s: Optional[str], sub: str) -> str:
|
|||
|
"""
|
|||
|
从字符串中删除所有指定的子串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 原字符串
|
|||
|
sub: 要删除的子串
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 删除后的字符串
|
|||
|
"""
|
|||
|
return await replace(s, sub, "")
|
|||
|
|
|||
|
|
|||
|
async def right(s: Optional[str], length: int) -> str:
|
|||
|
"""
|
|||
|
从右边获取指定长度的子字符串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 原字符串
|
|||
|
length: 要获取的长度
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 截取的子字符串
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return ""
|
|||
|
if length <= 0:
|
|||
|
return ""
|
|||
|
if length >= len(s):
|
|||
|
return s
|
|||
|
return s[-length:]
|
|||
|
|
|||
|
|
|||
|
async def left(s: Optional[str], length: int) -> str:
|
|||
|
"""
|
|||
|
从左边获取指定长度的子字符串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 原字符串
|
|||
|
length: 要获取的长度
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 截取的子字符串
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return ""
|
|||
|
if length <= 0:
|
|||
|
return ""
|
|||
|
return s[:length]
|
|||
|
|
|||
|
|
|||
|
async def length(s: Optional[str]) -> int:
|
|||
|
"""
|
|||
|
获取字符串的长度
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要测量的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
int: 字符串的长度,如果为None则返回0
|
|||
|
"""
|
|||
|
if s is None:
|
|||
|
return 0
|
|||
|
return len(s)
|
|||
|
|
|||
|
|
|||
|
async def reverse(s: Optional[str]) -> str:
|
|||
|
"""
|
|||
|
反转字符串
|
|||
|
|
|||
|
Args:
|
|||
|
s: 要反转的字符串
|
|||
|
|
|||
|
Returns:
|
|||
|
str: 反转后的字符串
|
|||
|
"""
|
|||
|
if await is_blank(s):
|
|||
|
return ""
|
|||
|
return s[::-1]
|