字符串工具 - StrUtil

由来

类似于 Apache Commons Lang 中的 StringUtil,使用 StrUtil 作为名称是因为更简洁。Str 这个简写已经深入人心,大家都明白是字符串的意思。

方法

判空方法

from hutool import StrUtil

# isEmpty / isNotEmpty —— 判断 null 或 ""
StrUtil.is_empty(None)     # True
StrUtil.is_empty("")       # True
StrUtil.is_empty("abc")    # False

# isBlank / isNotBlank —— 判断 null、"" 或空白字符
StrUtil.is_blank(None)     # True
StrUtil.is_blank("  \t\n") # True
StrUtil.is_blank("abc")    # False

# hasBlank / hasEmpty —— 多个字符串中是否有空
StrUtil.has_blank("abc", "", "def")   # True
StrUtil.has_empty("abc", None, "def") # True

# isAllBlank / isAllEmpty —— 是否全部为空
StrUtil.is_all_blank("", "  ", None)  # True

子串方法

sub 方法比原生切片更安全,支持负数索引且不会越界:

str_val = "abcdefgh"
StrUtil.sub(str_val, 2, 5)    # "cde"
StrUtil.sub(str_val, 2, -3)   # "cde"
StrUtil.sub(str_val, 3, 2)    # ""(自动修正顺序)

# subBefore / sub_after
StrUtil.sub_before("abc.def", ".")      # "abc"
StrUtil.sub_after("abc.def", ".")       # "def"
StrUtil.sub_before("abc.def", ".", True) # "abc"(从最后一个分隔符截取)

# subBetween
StrUtil.sub_between("aaBBccDD", "BB", "DD")  # "cc"

去前后缀

StrUtil.remove_prefix("pretty_girl.jpg", ".jpg")  # "pretty_girl"
StrUtil.remove_suffix("pretty_girl.jpg", "pretty_")  # "girl.jpg"
StrUtil.remove_prefix_ignore_case("ABCdef", "abc")  # "def"

格式化

灵感来自 slf4j 的 {} 占位符:

StrUtil.format("{}{},就像老鼠爱大米", "我", "你")
# "我爱你,就像老鼠爱大米"

命名转换

StrUtil.to_camel_case("hello_world")  # "helloWorld"
StrUtil.to_snake_case("helloWorld")   # "hello_world"
StrUtil.to_under_score_case("HelloWorld")  # "hello_world"

填充与重复

StrUtil.pad("abc", 6, "0")         # "abc000"
StrUtil.center("abc", 7, "*")      # "**abc**"
StrUtil.repeat("ab", 3)            # "ababab"
StrUtil.repeat_and_join(",", 3)    # ",,,"

分割与连接

StrUtil.split("a,b,c", ",")           # ["a", "b", "c"]
StrUtil.split("a,,b,c", ",", -1, False, True)  # ["a", "b", "c"](忽略空)

StrUtil.join(",", "a", "b", "c")      # "a,b,c"
StrUtil.join(",", ["a", "b", "c"])    # "a,b,c"

类型判断

StrUtil.is_numeric("123")      # True
StrUtil.is_number("123.45")    # True
StrUtil.is_alpha("abc")        # True
StrUtil.is_alpha_upper("ABC")  # True
StrUtil.is_alpha_lower("abc")  # True

统计

StrUtil.count("ababab", "ab")  # 3
StrUtil.count("ababab", "a")   # 3

替换

StrUtil.replace("aabbcc", "bb", "xx")         # "aaxxcc"
StrUtil.replace_first("aabbcc", "b", "x")      # "axbcc"
StrUtil.replace_chars("aabbcc", "ac", "x")      # "xxbbxx"

相似度

StrUtil.similar("hello", "hallo")    # 0.8
StrUtil.similar("hello", "hello")    # 1.0

文本分析

# 计算前导空白(tab 算 4 个空格)
StrUtil.left_space_count("    hello")  # 4
StrUtil.left_space_count("\thello")    # 4
StrUtil.left_space_count("hello")      # 0

# 查找子串所有出现位置
StrUtil.find_all_indices("abcabc", "bc")  # [1, 4]
StrUtil.find_all_indices("hello", "x")    # []

安全字符串处理

# 提取数字
StrUtil.only_digits("abc123def456")  # "123456"

# 全角/半角转换
StrUtil.full_to_half_width("Hello")  # "Hello"
StrUtil.half_to_full_width("Hello")        # "Hello"

# 移除中文字符
StrUtil.filter_chinese("你好World")  # "World"

# 移除中文标点
StrUtil.filter_chinese_punctuations("你好,World!")  # "你好World"

# 德语变音符号转 ASCII
StrUtil.de_umlaut("München")  # "Muenchen"

# Levenshtein 编辑距离
StrUtil.levenshtein_distance("kitten", "sitting")  # 3

比较与判断

# equalsAny / equalsAnyIgnoreCase
StrUtil.equals_any("hello", "hi", "hello", "hey")           # True
StrUtil.equals_any_ignore_case("Hello", "hi", "HELLO")     # True

# equalsCharAt
StrUtil.equals_char_at("hello", 0, "h")  # True

# containsOnly
StrUtil.contains_only("abc", "abcdef")  # True
StrUtil.contains_only("abc", "ab")       # False

# hasLetter
StrUtil.has_letter("hello123")  # True
StrUtil.has_letter("12345")     # False

# isSubEquals
StrUtil.is_sub_equals("hello world", "world", 6)  # True

# isSurround / isWrap
StrUtil.is_surround("[hello]", "[", "]")  # True
StrUtil.is_wrap("***hello***", "***")     # True

# isLowerCase / isUpperCase
StrUtil.is_lower_case("hello")  # True
StrUtil.is_upper_case("HELLO")  # True

# isAllCharMatch
StrUtil.is_all_char_match("123", str.isdigit)  # True

公共前缀/后缀与比较

StrUtil.common_prefix("flower", "flow", "flight")  # "fl"
StrUtil.common_suffix("testing", "running", "ing")  # "ing"

# null-safe 比较
StrUtil.compare("abc", "abd")           # -1
StrUtil.compare_ignore_case("ABC", "abc")  # 0

# 拼接(None 视为空串)
StrUtil.concat("a", None, "b", "c")  # "abc"

截取与格式化

# brief — 截断并加省略号(总长度不超过 max_length)
StrUtil.brief("hello world", 8)  # "hello..."

# maxLength — 截断并追加 "..."
StrUtil.max_length("hello world", 8)  # "hello..."

# fixLength — 填充或截断到固定长度
StrUtil.fix_length("hi", 5)       # "hi   "
StrUtil.fix_length("hello", 3)    # "hel"

# hide — 隐藏区间字符
StrUtil.hide("13812345678", 3, 7)  # "138****5678"

# normalize — 合并连续空白
StrUtil.normalize("  hello   world  ")  # "hello world"

# totalLength — 多字符串总长度
StrUtil.total_length("abc", None, "de")  # 5

# indexedFormat — 索引格式化
StrUtil.indexed_format("{0} + {1} = {2}", 1, 2, 3)  # "1 + 2 = 3"

包裹与填充

# wrap / wrapIfMissing
StrUtil.wrap("hello", "***")             # "***hello***"
StrUtil.wrap_if_missing("***hello***", "***")  # "***hello***"
StrUtil.wrap_if_missing("hello", "***")        # "***hello***"

# wrapAll / wrapAllIfMissing
StrUtil.wrap_all(["a", "b"], "[", "]")  # ["[a]", "[b]"]

# padAfter / padPre
StrUtil.pad_after("hi", 5)  # "hi   "
StrUtil.pad_pre("hi", 5)    # "   hi"

# repeatByLength
StrUtil.repeat_by_length("abc", 7)  # "abcabca"

高级替换与移除

# replaceIgnoreCase
StrUtil.replace_ignore_case("Hello HELLO", "hello", "hi")  # "hi hi"

# replaceLast — 字面量匹配(非正则)
StrUtil.replace_last("a.b.c", ".", "-")  # "a.b-c"

# removeAllPrefix / removeAllSuffix
StrUtil.remove_all_prefix("///path", "/")  # "path"
StrUtil.remove_all_suffix("path///", "/")  # "path"

# removeSufAndLowerFirst
StrUtil.remove_suf_and_lower_first("UserNameDTO", "DTO")  # "userName"

分割与转换

# splitTrim — 分割后 trim
StrUtil.split_trim(" a , b , c ")  # ["a", "b", "c"]

# stripAll
StrUtil.strip_all(" a ", " b ", None)  # ["a", "b", None]

# swapCase
StrUtil.swap_case("Hello World")  # "hELLO wORLD"

# toSymbolCase — 驼峰转符号分隔
StrUtil.to_symbol_case("helloWorld", "-")  # "hello-world"

# trimToNull
StrUtil.trim_to_null("  hello  ")  # "hello"
StrUtil.trim_to_null("   ")         # None

空值处理与杂项

# emptyIfNull
StrUtil.empty_if_null(None)     # ""
StrUtil.empty_if_null("hello")  # "hello"

# desensitized — 脱敏
StrUtil.desensitized("13812345678", 3, 4)  # "138****5678"

# compareVersion — 版本号比较
StrUtil.compare_version("1.2.3", "1.2.4")  # -1
StrUtil.compare_version("2.0", "1.9.9")    # 1

Unicode / CodePoint 操作

# subByCodePoint — 按码点截取(emoji 安全)
StrUtil.sub_by_code_point("a😀b😂c", 1, 3)  # "😀b"

# subSufByLength — 取最后 N 个字符
StrUtil.sub_suf_by_length("hello", 3)  # "llo"

# subWithLength — 从指定位置取指定长度
StrUtil.sub_with_length("hello", 1, 3)  # "ell"

# subPreGbk — 按 GBK 字节长度截断
StrUtil.sub_pre_gbk("你好世界", 6)  # "你好"(每个中文 2 字节)

# reverseByCodePoint — emoji 安全反转
StrUtil.reverse_by_code_point("a😀b")  # "b😀a"

# byteLength — 编码后字节长度
StrUtil.byte_length("你好")  # 6(UTF-8)

# length — null 安全长度
StrUtil.length(None)   # 0
StrUtil.length("abc")  # 3

分割扩展

# splitToLong / splitToInt — 分割为数字数组
StrUtil.split_to_long("1,2,3")  # [1, 2, 3]

# splitByLength — 按固定长度分割
StrUtil.split_by_length("abcdef", 2)  # ["ab", "cd", "ef"]

# splitIgnoreCase — 忽略大小写分割
StrUtil.split_ignore_case("aAbBcC", "b")  # ["aA", "", "cC"]

高级替换

# replaceFrom — 从指定位置开始替换
StrUtil.replace_from("aabbcc", 2, "b", "d")  # "aadbcc"

# replaceFirst/replaceLast — 支持 ignore_case
StrUtil.replace_first("Hello HELLO", "hello", "hi", ignore_case=True)
# "hi HELLO"

空值安全查找

# firstNonNull / firstNonEmpty / firstNonBlank
StrUtil.first_non_null(None, "b", "c")      # "b"
StrUtil.first_non_empty("", None, "b")       # "b"
StrUtil.first_non_blank("  ", None, "b")     # "b"

解包裹与字符级比较

# unwrap — 移除前后缀
StrUtil.unwrap("[hello]", "[", "]")  # "hello"

# isCharEquals — 所有字符是否相同
StrUtil.is_char_equals("aaa")  # True
StrUtil.is_char_equals("aab")  # False

# toString — null 返回 "null"
StrUtil.to_string(None)  # "null"

文本缩略

# shrinkRepeated — 压缩连续重复字符
StrUtil.shrink_repeated("aaaaabbbcc", 3)  # "aaabbbcc"
StrUtil.shrink_repeated("!!hello!!", 1)   # "!hello!"

中文标点替换

# subChinesePunctuations — 中文标点替换为英文标点
StrUtil.sub_chinese_punctuations("你好,世界!")  # "你好,世界!"

驼峰/下划线转换(增强)

# toCamelCase — 下划线转驼峰
StrUtil.to_camel_case("hello_world")    # "helloWorld"

# toSnakeCase — 驼峰转下划线(支持连续大写)
StrUtil.to_snake_case("HelloWorld")     # "hello_world"
StrUtil.to_snake_case("getHTTPResponse") # "get_http_response"

备注

更多方法请参阅 API 参考 文档。