当前位置: 首页 > news >正文

正则表达式 | Python、Julia 和 Shell 语法详解

正则表达式在网页爬虫、脚本编写等众多任务中都有重要的应用。为了系统梳理其语法,以及 Python、Julia 和 Shell 中与正则表达式相关的工具,本篇将进行详细介绍。

相关学习资源:编程胶囊。

基础语法

通用语法

在大多数支持正则表达式的语言中,以下规则是一致的,适用于 Shell、Python 和 Julia。

  1. 匹配位置

    • ^ 匹配字符串开头,$ 匹配字符串结尾,例如:
      • ^ab 匹配 abc, abcd, abb, ab
      • ^ab 不匹配 aab, aac, bab
      • ab$ 匹配 aab, ab, abab
      • ab$ 不匹配 aabb, b, abb
      • ^ab$ 精确匹配 ab
  2. 匹配字符

    匹配符说明
    .匹配除回车外的任意一个字符
    ( )字符串分组
    [ ]定义字符类,匹配括号中的任意一个字符
    \转义字符
    *匹配前一个字符若干次(包括 0 次)
    ?字符出现 0 次或 1 次
    +字符至少出现一次
    {n,}字符至少出现 n 次
    {n, m}字符至少出现 n 次,最多 m 次
    {m}字符正好出现 m 次
  3. 示例

    • ^a.c$ 匹配 abc, a.c, aec
    • ^a.c$ 不匹配 abbc, ac, .c
    • ^a\.c 精确匹配 a.c
    • ^a*c 匹配 c, ac, aac
    • ^a?c$ 仅匹配 c, ac
    • ^a+c$ 匹配 ac, aac
  4. 中括号表示匹配一个字符,其内部规则:

    • - 表示区间,注意右区间不能小于左区间,否则匹配无效。例如:
      • [2-8] 匹配数字 28
      • [a-c] 匹配字母 a, b, c
    • ^ 表示取反,例如 [^1-3] 匹配除了 1, 2, 3 以外的字符
    • \ 用于匹配特殊字符,例如 [\-] 匹配 -[\[] 匹配 [

贪婪匹配

  1. ? 的多重含义

    • 放在字符后,表示匹配 0 次或 1 次
    • 放在分组前,?: 表示不捕获分组内容
    • 用于断言时,?=, ?!, ?<=, ?<! 表示正向/反向断言
    • 放在可变长匹配后,表示非贪婪匹配,即尽可能少地匹配字符
  2. 示例

    reg1 = r"a{2,}"
    reg2 = r"a{2,}?"
    collect(eachmatch(reg1, "aaaaa"))
    # 贪婪匹配,匹配到一个元素 "aaaaa"
    collect(eachmatch(reg2, "aaaaa"))
    # 非贪婪匹配,匹配到两个 "aa", "aa"
    
  3. 贪婪匹配 vs 即停匹配
    比起“非贪婪匹配”,更合适的说法是“匹配即停”。
    对于可变长规则,贪婪匹配会尽可能多地匹配字符,而即停匹配在成功匹配到最短的子串后立即停止。

    reg1 = r"a.*b"
    reg2 = r"a.*?b"
    collect(eachmatch(reg1, "aaaaabaab"))
    # 贪婪匹配,匹配到 "aaaaabaab"
    collect(eachmatch(reg2, "aaaaabaab"))
    # 即停匹配,匹配到 "aaaaab" 和 "aab"
    

特殊匹配

  1. 以下规则在 Python 和 Julia 中一致,并与 Linux 的 Perl 兼容,而 shell 中的 grep 使用 POSIX 特殊字符,需要单独处理。

  2. 常见特殊字符

    • \w 匹配单词字符,包括 [a-zA-Z0-9_] 和汉字等,不包括符号
    • \d 匹配数字,等价于 [0-9]
    • \s 匹配空白字符,包括空格、制表符、换行符等
    • \b 匹配单词边界
      • 例如:\babc 匹配以 abc 开头的单词 abc, abcd, .abcdef
      • 不匹配 aabc, _abc, ababc
      • \b\w{4}\b 匹配长度为 4 的单词
    • \W, \D, \S 分别匹配 \w, \d, \s 的反例

分组

正则表达式提供了一种将表达式分组的机制,当使用分组时,除了获得整个匹配,还能够在匹配中选择每一个分组。

  1. 分组用括号抓取,比如

    • (\d{4})-(\d{2})-(\d{2}) 匹配并提取数据 2022-02-28 中的日期,一共三个分组
    ## Python 正则
    re.findall(r'(\d{4})-(\d{2})-(\d{2})', '2022-02-282321-02-21')
    # [('2022', '02', '28'), ('2321', '02', '21')]
    
    ## Julia 正则
    collect(eachmatch(r"(\d{4})-(\d{2})-(\d{2})", "2022-02-282321-02-21"))
    # RegexMatch("2022-02-28", 1="2022", 2="02", 3="28")
    # RegexMatch("2321-02-21", 1="2321", 2="02", 3="21")
    
  2. 分组内,使用“或”运算 |,比如

    • (\.jpg|\.png) 匹配 .jpg.png
    • (\.(jpg|png)) 嵌套匹配,两个分组,组1为 .jpg.png,组2为 jpgpng
    ### 匹配到两段信息,元组长度分别为 1
    collect(eachmatch(r"\d(\.jpg|\.png)", "1.jpg, 2.png"))
    # RegexMatch("1.jpg", 1=".jpg")
    # RegexMatch("2.png", 1=".png")
    ### 匹配到两端信息,元组长度分别为 2
    collect(eachmatch(r"\d(\.(jpg|png))", "1.jpg, 2.png"))
    # RegexMatch("1.jpg", 1=".jpg", 2="jpg")
    # RegexMatch("2.png", 1=".png", 2="png")
    
  3. 有时候,我们并不需要捕获某个分组的内容,但是又想使用分组的特性(比如或运算)。这个时候就可以使用非捕获组 (?:表达式),从而不捕获数据,还能使用分组的功能,比如匹配前缀和后缀,但只捕获前缀的分组

    ## Julia
    collect(eachmatch(r"(\w)\.(?:jpg|png)", "1.jpg, 2.png"))
    # RegexMatch("1.jpg", 1="1")
    # RegexMatch("2.png", 1="2")
    
    # Python
    re.findall(r"(\w)\.(?:jpg|png)", "1.jpg, 2.png")
    # ['1', '2']
    
  4. 分组的回溯引用,\N 表示表达式的第 N 个分组,比如

    collect(eachmatch(r"(\w)(\w)\2\1", "abbaddadda"))
    # RegexMatch("abba", 1="a", 2="b")
    # RegexMatch("adda", 1="a", 2="d")
    
    re.findall(r"(\w)(\w)\2\1", "abbaddadda")
    # [('a', 'b'), ('a', 'd')]
    

断言

正则表达式中的断言(Assertions)与 ^(匹配字符串开头)、$(匹配字符串结尾)或 \b(匹配单词边界)一样,都是用于匹配字符串中的某个位置,而不是匹配具体的字符。由于它们只匹配位置而不消耗字符,因此也称为“零宽断言”。

1. 断言类型

断言可以分为四种类型:

  • 正向先行断言(?=pattern)
  • 负向先行断言(?!pattern)
  • 正向后行断言(?<=pattern)
  • 负向后行断言(?<!pattern)
2. 正向先行断言

正向先行断言 (?=pattern) 匹配的是这样一个位置:该位置之后的字符序列可以匹配给定的 pattern。例如:

在字符串 a regular expression 中,我们想匹配单词 regular 中的 re,但不匹配 expression 中的 re,可以使用以下正则表达式:

re(?=gular)

这个表达式限定了匹配的 re 之后必须跟着 gular,但并不消耗 gular 这些字符。如果修改为 re(?=gular)g,则会匹配 reg,因为在 reg 之间的位置满足了 gular 的条件。

3. 负向先行断言

负向先行断言 (?!pattern) 匹配的是这样一个位置:该位置之后的字符序列不能匹配给定的 pattern。例如:

在字符串 regex represents regular expression 中,如果我们想匹配 regexregular 中的 re,但排除 representsexpression 中的 re,可以使用:

re(?!g)

这个表达式表示 re 之后不能有字母 g

4. 正向后行断言

正向后行断言 (?<=pattern) 匹配的是这样一个位置:该位置之前的字符序列可以匹配给定的 pattern。例如:

在字符串 regex represents regular expression 中,假设我们想匹配单词中的 re,但不匹配出现在单词开头的 re,可以使用:

(?<=\w)re

这里的断言要求 re 之前必须有一个单词字符(\w),所以不会匹配 regex 中的 re

5. 负向后行断言

负向后行断言 (?<!pattern) 匹配的是这样一个位置:该位置之前的字符序列不能匹配给定的 pattern。例如:

在字符串 regex represents regular expression 中,如果我们想排除匹配 representsexpression 中的 re,但匹配 regex 中的 re,可以使用:

(?<!\w)re

这表示 re 之前不能有任何单词字符。

6. 断言总结
  • 正向断言=,表示断言的条件必须成立;
  • 负向断言!,表示断言的条件不能成立;
  • 先行断言从当前位置开始向后匹配,限定该位置之后的字符;
  • 后行断言从当前位置开始向前匹配,限定该位置之前的字符。
7. 断言示例

为了更好地理解断言,我们可以以字符串 regex represents regular expression 为例,尝试几种断言组合:

  • 正向先行断言re(?=g) 限定 re 之后必须有 g,因此匹配 regexregular 中的 re,排除了 representsexpression 中的 re
  • 负向先行断言re(?!s|p) 限定 re 之后不能是 sp,匹配了 regexregularre,排除了 representsexpression
  • 正向后行断言(?<=r)e 限定 e 之前必须是 r,匹配所有单词中的 e
  • 负向后行断言(?<!p)re 限定 re 之前不能是 p,排除了 representsexpression 中的 re
8. 经典断言应用

我们可以用断言来匹配一个同时包含大小写字母的非空字符串。例如:

(?=.*?[a-z])(?=.*?[A-Z]).+

解释:

  • (?=.*?[a-z]) 匹配包含至少一个小写字母的位置;
  • (?=.*?[A-Z]) 匹配包含至少一个大写字母的位置;
  • 最后的 .+ 表示字符串本身至少有一个字符。

通过这种方式,两个断言结合,确保字符串同时包含大写和小写字母。类似地,我们可以使用 (?=.*?[a-z]{m,}) 来匹配至少包含 m 个小写字母的位置。

Shell

  1. grep -Eegrep 命令
    在 Shell 中,可以使用 grep -Eegrep 命令进行正则表达式匹配。需要注意的是,默认的 grepgrep -e,而 -e 只支持基础正则表达式(BRE),这会导致一些高级的正则语法无法使用。例如,grep a?c 在默认模式下不会匹配 acc

  2. POSIX 特殊字符
    POSIX 标准定义了一组特殊字符类,这些字符类可用于匹配特定的字符类型。在使用 grep 时,可以通过 [:class:] 来引用这些字符类。

    特殊字符说明
    [:alnum:]匹配任意字母字符和数字(0-9a-zA-Z
    [:alpha:]匹配任意字母字符(大写或小写)
    [:digit:]匹配数字 0-9
    [:graph:]匹配除空格外的所有可打印字符
    [:lower:]匹配小写字母 a-z
    [:upper:]匹配大写字母 A-Z
    [:cntrl:]匹配控制字符
    [:print:]匹配所有可打印字符,包括空格
    [:punct:]匹配标点符号
    [:blank:]匹配空格和制表符
    [:xdigit:]匹配十六进制数字
    [:space:]匹配所有空白字符(如换行符、空格、制表符)
  3. 外层字符匹配
    在使用 POSIX 字符类时,通常需要将它们放在方括号内。例如:

    grep '[[:alpha:]]' filename  # 匹配文件中的字母字符
    

Julia

在 Julia 中,正则表达式通过 r 前缀表示,使用非常灵活,并且支持与 Python 类似的丰富功能。推荐参考 Julia 官方文档。

  1. 基本使用
    在 Julia 中,使用 r"..." 来定义正则表达式。例如:

    re = r"^\s*(?:#|\$)"
    typeof(re)  # 输出: Regex
    isconcretetype(Regex)  # 输出: true
    

    该正则表达式匹配以若干空格开头,后跟 #$ 的字符串。其具体语法为:

    • ^:匹配行首;
    • \s*:匹配若干空白字符;
    • (?:...):非捕获组,用于组合多个条件;
    • #|\$:匹配 #$
  2. occursinmatch

    • occursin 用于判断字符串中是否存在匹配项:
    occursin(r"^\s*(?:#|\$)", "# a comment")  # 输出: true
    
    • match 用于获取具体的匹配结果:
    m = match(r"(\d{2})([a-z]{2})", "aa12bb34cc")
    m.match  # 输出: "12bb"
    m.captures  # 输出: ["12", "bb"]
    m.offset  # 匹配的起始位置
    m.offsets  # 每个捕获组的起始位置
    
  3. 分组命名和回溯引用
    Julia 支持命名分组,并且允许通过名称或索引来引用分组:

    m = match(r"(?<tag>\d+):(\d+)", "12:45")
    m[:tag]  # 使用标签调用分组,输出: "12"
    m[2]  # 使用索引调用分组,输出: "45"
    

    同时,支持回溯调用分组内容:

    m = match(r"(?P<hi>\d+):\g<hi>", "12:12")  # 用 \g<hi> 调用分组
    m = match(r"(?<hi>\d+):\g1", "12:12")  # 使用分组序号
    
  4. replace 函数
    replace 函数在 Julia 中支持正则表达式,并允许使用捕获组中的内容:

    replace("--12:34--", r"(?<hour>\d+):(?<minute>\d+)" => s"\g<minute>")  # 输出: "--34--"
    
  5. eachmatch 函数
    eachmatch 返回一个 RegexMatch 对象的迭代器,用于多项匹配:

    collect(eachmatch(r"\d\d", "1234"))  # 输出: 两个匹配项 ["12", "34"]
    
  6. 换行匹配
    . 无法匹配换行符,要匹配换行符可以使用 [\s\S][\w\W]

    match(r"123[\s\S]321", "123\n22\n321")  # 输出: RegexMatch("123\n22\n321")
    

Python

Python 自 1.5 版本起增加了 re 模块,它提供 Perl 风格的正则表达式模式。

  1. match 从字符起始位置开始匹配

    re.match(r"\d\d", "2a-2b\n20") # 返回 None,未匹配到
    re.match(r"\w\w", "2a-2b\n20") # 返回匹配对象
    # <re.Match object; span=(0, 2), match='2a'>
    
  2. search 扫描整个字符串,并返回第一个成功匹配的位置

    re.search(r"\d\d", "2a-2b\n20")
    # <re.Match object; span=(6, 8), match='20'>
    info = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "ab2022-03-01cd")
    print(info.start()) # 2 | 匹配到的起始位置
    print(info.end()) # 12 | 匹配到的终点位置
    info.span() # (2, 12) | 起始 和 终点
    print(info.groups()) # ('2022', '03', '01') | 分组内容
    print(info.group(0)) # 2022-03-01 | 位置 0 代表匹配的字符串
    info.group() # 等同于 info.group(0)
    info.group(1) # 2022 | 位置 1 代表分组第一个元素
    info.regs # ((2, 12), (2, 6), (7, 9), (10, 12)) | 分组内容的索引
    info.re # 返回使用的正则匹配规则
    info.string # 返回被匹配的字符串
    info.groupdict() # {'year': '2022', 'month': '03', 'day': '01'} | 字典形式返回匹配内容
    

    匹配对象的常用属性和方法
    深度截图_选择区域_20220305155144

  3. sub 检索和替换

    # 提取日期,并将格式的 - 改为 /
    txt = "ab2022-03-01cd"
    reg = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
    repl = r"\1/\2/\3"
    re.sub(reg, repl, txt) # 'ab2022/03/01cd'
    
  4. compile 编译正则表达式,搭配其他函数使用

    reg = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})") # 编译正则表达式
    reg.search("ab2022-03-01cd") # 返回查找对象
    
  5. findall 查找所有匹配的字符串

    re.findall("\w{2}", "2022-03-01") # 返回字符串构成的列表
    # ['20', '22', '03', '01']
    re.findall("(\w{2})-(\w{2})", "20-22-03-01") # 返回字符串元组构成的列表
    # [('20', '22'), ('03', '01')]
    
  6. finditer 返回迭代器形式的匹配信息

    list(re.finditer("\w{2}", "2022-03-01"))
    # [<re.Match object; span=(0, 2), match='20'>,
    # <re.Match object; span=(2, 4), match='22'>, 
    # <re.Match object; span=(5, 7), match='03'>, 
    # <re.Match object; span=(8, 10), match='01'>]
    
  7. split 按匹配规则进行字符串拆分

    re.split("\d", "1bb3cc1dd")
    # ['', 'bb', 'cc', 'dd']
    
  8. 在使用以上函数时,支持修饰符,且多个修饰符用 | 指定,比如

    re.findall(r"ab.*cd", "ab\ndd\nCD") # [] | 换行匹配不到
    re.findall(r"ab.*cd", "ab\ndd\nCD", re.I | re.S) # ['ab\ndd\nCD'] | `.` 可以匹配换行,字母不分大小写
    
  9. 常见修饰符

修饰符描述
re.I使匹配对大小写不敏感
re.L做本地化识别匹配
re.M多行匹配,影响 ^$
re.S使 . 匹配包括换行在内的所有字符
re.U根据 Unicode 字符集解析字符。这个标志影响 \w, \W, \b, \B
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

Python

Python 自 1.5 版本起引入了 re 模块,提供了类似 Perl 风格的正则表达式功能。以下是常用的正则操作:

  1. match 从字符串起始位置开始匹配:

    re.match(r"\d\d", "2a-2b\n20")  # 返回 None,未匹配到
    re.match(r"\w\w", "2a-2b\n20")  # 返回匹配对象
    # <re.Match object; span=(0, 2), match='2a'>
    
  2. search 扫描整个字符串并返回第一个匹配项:

    re.search(r"\d\d", "2a-2b\n20")
    # <re.Match object; span=(6, 8), match='20'>
    info = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "ab2022-03-01cd")
    print(info.groups())  # ('2022', '03', '01')
    info.groupdict()  # {'year': '2022', 'month': '03', 'day': '01'}
    
  3. sub 查找并替换匹配的字符串:

    txt = "ab2022-03-01cd"
    reg = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
    repl = r"\1/\2/\3"
    re.sub(reg, repl, txt)  # 输出: 'ab2022/03/01cd'
    
  4. compile 编译正则表达式,以提高效率:

    reg = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})")
    reg.search("ab2022-03-01cd")  # 返回匹配对象
    
  5. findall 查找所有匹配的项并返回列表:

    re.findall(r"\w{2}", "2022-03-01")  # 返回 ['20', '22', '03', '01']
    
  6. finditer 返回迭代器形式的匹配对象:

    matches = list(re.finditer(r"\w{2}", "2022-03-01"))
    for match in matches:print(match.group())  # 输出匹配的子串
    
  7. split 按照正则表达式拆分字符串:

    re.split(r"\d", "1bb3cc1dd")  # 输出: ['', 'bb', 'cc', 'dd']
    
  8. 修饰符 支持多种正则修饰符,多个修饰符可用 | 组合使用:

    re.findall(r"ab.*cd", "ab\ndd\nCD", re.I | re.S)  # ['ab\ndd\nCD'] | `.` 可匹配换行且不区分大小写
    
  9. 常见修饰符表

    修饰符说明
    re.I匹配时忽略大小写
    re.M多行模式,影响 ^$
    re.S使 . 匹配所有字符,包括换行符
    re.X允许更灵活的格式,使正则表达式更易于理解

Perl

Perl 是正则表达式的先驱语言之一,其强大的正则功能被很多现代编程语言借鉴。我们可以通过 Shell 中的 grep -P 来使用 Perl 风格的正则表达式。以下是 Perl 和 Python 正则表达式的一些比较和补充:

  1. Perl 中的正则语法
    Perl 使用类似于 Python 的正则表达式语法,但增加了一些独有的功能。比如,Perl 支持更复杂的嵌套分组和条件匹配。

  2. 捕获和命名分组
    Perl 支持命名捕获组和回溯引用,类似于 Python:

    # Perl 写法
    if ($str =~ /(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})/) {print "$+{year}/$+{month}/$+{day}\n";  # 使用命名分组
    }
    
  3. 正则表达式修饰符
    Perl 提供了强大的修饰符功能,包括 m(多行模式)、s(单行模式)、x(扩展模式)等,类似 Python 的修饰符机制:

    $str =~ /pattern/i;  # 大小写不敏感匹配
    $str =~ /pattern/s;  # 允许 `.` 匹配换行符
    
  4. grep -P
    在 shell 中,grep -P 允许你使用 Perl 的正则表达式语法来进行文本处理:

    grep -P '\d{4}-\d{2}-\d{2}' file.txt  # 使用 Perl 风格的正则表达式匹配日期
    
  5. 扩展和嵌套正则
    Perl 支持复杂的条件表达式和递归模式匹配,例如在括号匹配或 XML 解析等应用场景中非常强大。

相关文章:

正则表达式 | Python、Julia 和 Shell 语法详解

正则表达式在网页爬虫、脚本编写等众多任务中都有重要的应用。为了系统梳理其语法&#xff0c;以及 Python、Julia 和 Shell 中与正则表达式相关的工具&#xff0c;本篇将进行详细介绍。 相关学习资源&#xff1a;编程胶囊。 基础语法 通用语法 在大多数支持正则表达式的语…...

JavaScript全面指南(一)

​ &#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript全面指南(一) 1、介绍一下JS的内置类型有哪些&#xff1f; 基本数据类型…...

docker-compose与docker

“docker-compose” 是一个用于定义和运行多容器 Docker 应用程序的工具。它使用一个名为 docker-compose.yml 的配置文件来描述应用程序的服务、网络和卷&#xff0c;然后通过简单的命令就可以管理整个应用。 以下是一些常用的 docker-compose 命令及其用法&#xff1a; 启动…...

DDPM浅析

在机器学习和人工智能领域&#xff0c;生成模型一直是一个备受关注的研究方向。近年来&#xff0c;一种新型的生成模型——扩散概率模型&#xff08;Diffusion Probabilistic Models&#xff0c;简称DDPM&#xff09;引起了广泛的关注。本文将探讨DDPM的原理、优势以及应用。 …...

力扣刷题-算法基础

hello各位小伙伴们,为了进行算法的学习,小编特意新开一个专题来讲解一些算法题 1.移除元素. - 力扣(LeetCode) 本题大概意思是给定一个数组和一个数val删除与val相同的元素,不要改变剩余元素的顺序,最后返回剩余元素的个数。 我们在这里使用双指针,这里的双指针并不是…...

理解 Python 中的 Hooks 和装饰器

Python 中的 hooks 和装饰器&#xff0c;虽然它们看起来都有些魔法加成&#xff0c;但实际上各有妙用。下面看看他们到底是做什么的吧。 什么是 Hooks&#xff1f; Hooks 是指在某些操作或事件发生时&#xff0c;可以将自定义的代码插入和执行的一种机制。它们常用于扩展和修…...

Android 原生程序使用gdb, addr2line, readelf调试

Platform: RK3368 OS: Android 6.0 Kernel: 3.10.0 文章目录 一 gdb1. 原生程序添加调试符号2. 主机上adb push 编译好的原生程序到设备3. 设备上使用gdbserver运行原生程序4. 主机上设置adb端口转发5. 主机上运行gdb调试 二 addr2line三 readelf 一 gdb GDB&#xff08;GNU…...

PHP 函数 func_num_args() 的作用

func_num_args() 是 PHP 中的一个内置函数&#xff0c;用于获取传递给当前用户定义函数的参数个数。这个函数特别有用于处理可变数量的参数&#xff08;也称为可变参数列表&#xff09;。 语法 int func_num_args ( void ) 返回值 func_num_args() 返回一个整数&#xff0c…...

深入解析单片机原理及其物联网应用:附C#示例代码

深入解析单片机原理及其物联网应用&#xff1a;附C#示例代码 随着物联网技术的快速发展&#xff0c;单片机作为嵌入式系统的核心&#xff0c;已经广泛应用于各类智能设备中。本文将从单片机的原理出发&#xff0c;结合C#编程的物联网示例&#xff0c;带你深入了解如何利用单片…...

HTTP 和 WebSocket

目录 HTTP是什么HTTP局限性&#xff08;HTTP1.1&#xff09;请求和响应HTTP的主要特点&#xff1a;HTTP版本&#xff1a; HTTP与TCP关系数据封装传输过程1. **协议层次模型**&#xff1a;2. **封装过程**&#xff1a;1. **应用层&#xff08;HTTP&#xff09;**&#xff1a;2. …...

科技云报到:大模型时代下,向量数据库的野望

科技云报到原创。 自ChatGPT爆火&#xff0c;国内头部平台型公司一拥而上&#xff0c;先后发布AGI或垂类LLM&#xff0c;但鲜有大模型基础设施在数据层面的进化&#xff0c;比如向量数据库。 在此之前&#xff0c;向量数据库经历了几年的沉寂期&#xff0c;现在似乎终于乘着Ch…...

贪吃蛇游戏(代码篇)

我们并不是为了满足别人的期待而活着。 前言 这是我自己做的第五个小项目---贪吃蛇游戏&#xff08;代码篇&#xff09;。后期我会继续制作其他小项目并开源至博客上。 上一小项目是贪吃蛇游戏&#xff08;必备知识篇&#xff09;&#xff0c;没看过的同学可以去看看&#xf…...

数控走心机系统可以定制吗

当然&#xff0c;走心机系统是可以定制的。随着数控技术的不断发展&#xff0c;走心机的数控系统越来越灵活&#xff0c;可以根据用户的具体需求进行定制和优化。下面&#xff0c;我将从几个方面来详细解答这个问题&#xff1a; ‌一、系统定制的必要性‌ ‌1. 满足不同加工需求…...

PHP实现OID(Object identifier)的编码和解码

转载于&#xff1a;https://bkssl.com/document/php_oid_encode_decode.html <?phpclass ASN1ObjectIdentifier {/*** OID字符串编码为二进制数据* param string $oid 字符串形式的OID* return string*/public static function encode($oid){$parts explode(., $oid);$pa…...

架构设计笔记-12-信息系统架构设计理论与实践

目录 知识要点 案例分析 1.Java企业级应用系统 2.c/s架构&#xff0c;b/s架构 知识要点 软件架构风格是描述某一特定应用领域中系统组织方式的惯用模式。架构风格定义了一类架构所共有的特征&#xff0c;主要包括架构定义、架构词汇表和架构约束。 数据挖掘是从数据库的大…...

【Power Compiler手册】15.多角多模式设计中的功耗优化

多角多模式设计中的功耗优化 可以使用多个运行条件和多种模式进行综合的设计被称为多角多模式设计。Design Compiler Graphical工具扩展了拓扑技术,以分析和优化这些设计。 有关多角多模式技术支持的综合工具的更多信息,请参见以下主题: • 优化多角多模式设计 • 报告命…...

关于HalconDeeplearn中的语义分割的实现

1.读取数据和数据集 read_dl_model (C:/Users/user/Desktop/大蒜测试/包裹/model_训练-240926-191345_opt.hdl, DLModelHandle) read_dict(C:/Users/user/Desktop/大蒜测试/包裹/model_训练-240926-162708_opt_dl_preprocess_params.hdict,[], [], DLDataset) 2.读取识别图片 I…...

【STL】AVLTree模拟实现

AVLTree模拟实现 1 前言2 AVL树的插入2.1 平衡因子不继续向上更新的情况2.2 平衡因子变为2或者-2&#xff0c;发生旋转2.2.1 左单旋2.2.2 右单旋2.2.3 左右双旋2.2.4 右左双旋 3 代码 1 前言 二叉搜索树的不足&#xff1a;如果出现极端情况&#xff0c;效率会变得很低。 AVL&am…...

无极低码课程【tomcat部署windows环境厂家乱码处理】

windows 下tomcat安装 下载地址一:https://tomcat.apache.org/download-90.cgi 下载地址二:https://archive.apache.org/dist/tomcat/ 解压tomcat,进入bin目录运行startup.bat...

注册安全分析报告:惠农网

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…...

Qualitor checkAcesso.php 任意文件上传漏洞复现(CVE-2024-44849)

0x01 漏洞概述 Qualitor 8.24及之前版本存在任意文件上传漏洞,未经身份验证远程攻击者可利用该漏洞代码执行,写入WebShell,进一步控制服务器权限。 0x02 复现环境 FOFA:app="Qualitor-Web" 0x03 漏洞复现 PoC POST /html/ad/adfilestorage/request/checkAcess…...

PHP-FPM和FastCGI

文章目录 前言一. FastCGI1.定义2.工作方式3.协议4.架构5.工作原理&#xff08;请求生命周期&#xff09; 二. PHP-FPM1.定义&#xff1a;2.特性3.进程管理模式4.工作流程 三.关系与应用四.配置示例五.性能优化六.配置选项七.常见问题及解决方案 前言 PHP-FPM 是基于 FastCGI …...

【Linux快速入门(二)】Linux与ROS学习之编译基础(make编译)

目录 零.前置篇章 一.make的由来 二.安装make 三.编写Makefile 四.编译运行 五.删除可执行文件 零.前置篇章 第一篇【Linux快速入门】Linux与ROS学习之编译基础&#xff08;gcc编译&#xff09;_linuxros-CSDN博客 一.make的由来 "make"是一个用于自…...

jupyterlab的安装与使用攻略/包括汉化方法

官网链接 Project Jupyter | Home 1.第一步安装 打开控制台 使用pip工具安装 pip install jupyterlab 如图 2.安装成功后启动 jupyter lab 会自动启动它的web页面 然后就可以正常使用咯&#xff01;&#xff01; 如果需要更换浏览器访问 新开控制台执行下面命令 jupy…...

std::list

std::list是C标准库中的一个序列容器&#xff0c;它提供了双向链表的功能。std::list允许在序列的任何位置高效地插入和删除元素&#xff0c;而不会引起其他元素的移动&#xff0c;这使得std::list在需要频繁插入和删除操作的场景中非常有用。 std::list的特性&#xff1a; 双…...

opencv-rust 系列2: camera_calibration

opencv-rust 系列2: camera_calibration 前言: 这里只是opencv-rust自带示例的中文注解. 略微增加了一些代码也是我在调试时用到的. 说明: camera_calibration.rs是opencv-rust自带的示例, 在examples目录中可以找到,我增加了一些中文注释如下.如需运行可以在项目根目录执行命…...

JVM和GC案例详解

接上文JVM环境配置说明&#xff1a;上文博客 一、JVM远程连接设置 1. JMX方式连接(这种方式没有GC监控)&#xff0c;设置如下 2. 连接成功后可以查看基础配置参数(和服务器配置一致) 2. jstatd方式连接(这种方式没有CPU监控) 添加jstatd方式连接 双击Tomcat&#xff0…...

postgreSql下载安装

一、下载 官网&#xff1a;PostgreSQL: The worlds most advanced open source database 二、安装 1.找到.exe文件&#xff0c;双击安装 2.跟着安装向导操作 三、启动...

GPT-SOVIT模型部署指南

一、模型介绍 强大的小样本语音转换和文本转语音 WebUI。 具有以下特征&#xff1a; 零样本 TTS&#xff1a; 输入 5 秒的声音样本并体验即时文本到语音的转换。少量样本 TTS&#xff1a; 仅使用 1 分钟的训练数据对模型进行微调&#xff0c;以提高语音相似度和真实感。跨语…...

怎么定时发朋友圈?

要实现微信朋友圈的定时发布&#xff0c;可以采用以下几种方法&#xff1a; 1、 绑定QQ号并使用QQ空间定时功能&#xff1a; 于微信和QQ的紧密联系&#xff0c;可以通过绑定QQ号&#xff0c;利用QQ空间的定时发布功能来间接实现微信朋友圈的定时发布。首先&#xff0c;在QQ空…...