正则表达式匹配不包含指定字符串的文本实例演示

Written by

in

文章目录
  • 在日常的文本处理、数据筛选场景中,我们经常需要反向匹配——找出不包含某个特定字符串的文本内容。正则表达式本身擅长“匹配存在的内容”,但通过“负向环视”特性,我们可以轻松实现这一反向需求。
  • 要匹配不包含指定字符串(如 target)的文本,核心正则表达式如下: ^(?!.*target).*$
  • 匹配“不包含指定字符串”的核心是负向环视 (?!…),基础模板为 ^(?!.*目标字符串).*$; 让 . 匹配换行符需开启单行模式:PHP /s、Java Pattern.DOTALL、Golang (?s)、JavaScript /s、C++ dotall、Python re.S; 多语言按行匹配需开启多行模式:PHP /m、Java Pattern.MULTILINE、Golang (?m)、JavaScript /m、C++ multiline、Python re.M; 排除多个字符串时,叠加多个负向环视断言即可,逻辑简单且易扩展; 不同语言的正则语法和标志略有差异,但核心原理相通,掌握一种后可快速迁移到其他语言。 到此这篇关于正则表达式匹配不包含指定字符串的文本的文章就介绍到这了,更多相关正则表达式匹配不包含指定字符串内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: 正则表达式匹配不包含某些字符串的技巧 正则表达式模式匹配字符串基础知识 js 正则表达式学习笔记之匹配字符串 java如何用正则表达式匹配与提取字符串 python正则表达式对字符串的查找匹配 Python 正则表达式匹配字符串中的http链接方法
  • 目录
    • 前言
    • 原理:负向环视(Negative Lookahead)
      • 表达式逐部分解析
    • 实例演示
      • PHP 示例
      • Java 示例
      • Go 示例
      • JavaScript 示例
      • C++ 示例
      • Python 示例
    • 扩展场景
      • 1. 排除多个字符串
        • Python 示例(匹配不包含 foo 和 bar 的文本)
        • PHP 示例(匹配不包含 foo 和 bar 的文本)
        • Java 示例(匹配不包含 foo 和 bar 的文本)
        • Go 示例(匹配不包含 foo 和 bar 的文本)
      • 补充说明
        • 2. 同时开启多行+单行模式
        • 总结

          在日常的文本处理、数据筛选场景中,我们经常需要反向匹配——找出不包含某个特定字符串的文本内容。正则表达式本身擅长“匹配存在的内容”,但通过“负向环视”特性,我们可以轻松实现这一反向需求。

          要匹配不包含指定字符串(如 target)的文本,核心正则表达式如下:

          ^(?!.*target).*$

          表达式片段 具体含义
          ^ 匹配字符串的开头位置,确保从文本最起始处开始检查
          (?!.*target) 负向环视(负向前瞻断言):
          ?! 表示“断言当前位置后不存在指定模式”;
          .* 匹配任意字符(除换行符外,单行模式除外)任意次数;
          – 整体作用:从开头位置检查,确保后续所有内容中都找不到 target
          .* 匹配符合“不包含 target”条件的任意字符(除换行符)任意次数,即文本主体内容
          $ 匹配字符串的结尾位置,确保检查覆盖到文本末尾

          效果:该表达式仅匹配“从开头到结尾完整、且全程不包含 target”的字符串,只要文本中出现 target,匹配立即失败。

          <?php
          // 待处理的多行文本(包含换行的跨行文内容)
          $text = "
          hello world
          test target 123
          php regex demo
          这是跨换行的内容
          foo target bar
          no match here
          ";
          
          // 场景1:仅按行匹配(不跨换行)
          echo "=== 场景1:仅按行匹配(不跨换行)===n";
          $regex1 = '/^(?!.*target).*$/m';
          preg_match_all($regex1, $text, $matches1);
          foreach ($matches1[0] as $match) {
              $match = trim($match);
              if ($match !== "") {
                  echo $match . "n";
              }
          }
          
          // 场景2:跨换行匹配整段内容(/s 开启单行模式)
          echo "n=== 场景2:跨换行匹配整段内容 ===n";
          $regex2 = '/^(?!.*target).*$/s';
          // 用 preg_match 匹配整段,而非 preg_match_all
          $isFullMatch = preg_match($regex2, $text);
          if (!$isFullMatch) {
              echo "整段文本包含 target,匹配失败n";
          }
          
          // 测试无 target 的跨行文本
          $textNoTarget = "
          hello php
          这是跨换行的内容
          无 target 字符串
          ";
          $isNoTargetMatch = preg_match($regex2, $textNoTarget);
          if ($isNoTargetMatch) {
              echo "n无 target 的跨行文本匹配结果:n";
              echo trim($textNoTarget) . "n";
          }
          ?>
          

          运行结果

          === 场景1:仅按行匹配(不跨换行)===
          hello world
          php regex demo
          这是跨换行的内容
          no match here
          
          === 场景2:跨换行匹配整段内容 ===
          整段文本包含 target,匹配失败
          
          无 target 的跨行文本匹配结果:
          hello php
          这是跨换行的内容
          无 target 字符串
          

          import java.util.regex.Matcher;
          import java.util.regex.Pattern;
          
          public class RegexNoTarget {
              public static void main(String[] args) {
                  // 待处理的多行文本(包含换行的跨行文内容)
                  String text = """
                          hello world
                          test target 123
                          java regex demo
                          这是跨换行的内容
                          foo target bar
                          no match here
                          """;
                  
                  // 场景1:仅按行匹配(不跨换行)
                  System.out.println("=== 场景1:仅按行匹配(不跨换行)===");
                  String regex1 = "^(?!.*target).*$";
                  Pattern pattern1 = Pattern.compile(regex1, Pattern.MULTILINE);
                  Matcher matcher1 = pattern1.matcher(text);
                  while (matcher1.find()) {
                      String match = matcher1.group().trim();
                      if (!match.isEmpty()) {
                          System.out.println(match);
                      }
                  }
          
                  // 场景2:跨换行匹配整段内容(开启 DOTALL)
                  System.out.println("n=== 场景2:跨换行匹配整段内容 ===");
                  String regex2 = "^(?!.*target).*$";
                  Pattern pattern2 = Pattern.compile(regex2, Pattern.DOTALL);
                  Matcher matcher2 = pattern2.matcher(text);
                  if (matcher2.matches()) {
                      System.out.println(matcher2.group());
                  } else {
                      System.out.println("整段文本包含 target,匹配失败");
                  }
          
                  // 测试无 target 的跨行文本
                  String textNoTarget = """
                          hello java
                          这是跨换行的内容
                          无 target 字符串
                          """;
                  Matcher matcher3 = pattern2.matcher(textNoTarget);
                  if (matcher3.matches()) {
                      System.out.println("n无 target 的跨行文本匹配结果:");
                      System.out.println(matcher3.group().trim());
                  }
              }
          }
          

          运行结果

          === 场景1:仅按行匹配(不跨换行)===
          hello world
          java regex demo
          这是跨换行的内容
          no match here
          
          === 场景2:跨换行匹配整段内容 ===
          整段文本包含 target,匹配失败
          
          无 target 的跨行文本匹配结果:
          hello java
          这是跨换行的内容
          无 target 字符串
          

          package main
          
          import (
          	"fmt"
          	"regexp"
          	"strings"
          )
          
          func main() {
          	// 待处理的多行文本(包含换行的跨行文内容)
          	text := `
          hello world
          test target 123
          golang regex demo
          这是跨换行的内容
          foo target bar
          no match here
          	`
          
          	// 场景1:仅按行匹配(不跨换行)
          	fmt.Println("=== 场景1:仅按行匹配(不跨换行)===")
          	regex1 := regexp.MustCompile(`(?m)^(?!.*target).*$`)
          	matches1 := regex1.FindAllString(text, -1)
          	for _, match := range matches1 {
          		match = strings.TrimSpace(match)
          		if match != "" {
          			fmt.Println(match)
          		}
          	}
          
          	// 场景2:跨换行匹配整段内容((?s) 开启单行模式)
          	fmt.Println("n=== 场景2:跨换行匹配整段内容 ===")
          	regex2 := regexp.MustCompile(`(?s)^(?!.*target).*$`)
          	// 用 MatchString 判断整段是否匹配,更严谨
          	isFullMatch := regex2.MatchString(text)
          	if !isFullMatch {
          		fmt.Println("整段文本包含 target,匹配失败")
          	}
          
          	// 测试无 target 的跨行文本
          	textNoTarget := `
          hello golang
          这是跨换行的内容
          无 target 字符串
          	`
          	isNoTargetMatch := regex2.MatchString(textNoTarget)
          	if isNoTargetMatch {
          		fmt.Println("n无 target 的跨行文本匹配结果:")
          		fmt.Println(strings.TrimSpace(textNoTarget))
          	}
          }
          

          运行结果

          === 场景1:仅按行匹配(不跨换行)===
          hello world
          golang regex demo
          这是跨换行的内容
          no match here
          
          === 场景2:跨换行匹配整段内容 ===
          整段文本包含 target,匹配失败
          
          无 target 的跨行文本匹配结果:
          hello golang
          这是跨换行的内容
          无 target 字符串
          

          // 待处理的多行文本
          const text = `
          hello world
          test target 123
          javascript regex demo
          这是跨换行的内容
          foo target bar
          no match here
          `;
          
          // 无 target 的跨行测试文本
          const textNoTarget = `
          hello javascript
          这是跨换行的内容
          无 target 字符串
          `;
          
          // 场景1:仅按行匹配(开启多行模式 m)
          console.log("=== 场景1:仅按行匹配(不跨换行)===");
          const regex1 = /^(?!.*target).*$/m;
          // 用 match 直接提取所有匹配行,更简洁
          const matches1 = text.match(regex1) || [];
          matches1.forEach(line => {
              const trimmed = line.trim();
              if (trimmed) {
                  console.log(trimmed);
              }
          });
          
          // 场景2:跨换行匹配整段内容(开启单行模式 s)
          console.log("n=== 场景2:跨换行匹配整段内容 ===");
          const regex2 = /^(?!.*target).*$/s;
          if (!regex2.test(text)) {
              console.log("整段文本包含 target,匹配失败");
          }
          
          // 匹配无 target 的文本
          if (regex2.test(textNoTarget)) {
              console.log("n无 target 的跨行文本匹配结果:");
              console.log(textNoTarget.trim());
          }
          

          运行环境:浏览器控制台/Node.js(v10+ 支持 s 修饰符)

          运行结果

          === 场景1:仅按行匹配(不跨换行)===
          hello world
          javascript regex demo
          这是跨换行的内容
          no match here
          
          === 场景2:跨换行匹配整段内容 ===
          整段文本包含 target,匹配失败
          
          无 target 的跨行文本匹配结果:
          hello javascript
          这是跨换行的内容
          无 target 字符串
          

          #include <iostream>
          #include <regex>
          #include <string>
          #include <iterator>
          #include <algorithm>
          
          // 完善 trim 函数,处理全空白字符串
          std::string trim(const std::string& str) {
              const std::string whitespace = " tnr";
              const size_t start = str.find_first_not_of(whitespace);
              if (start == std::string::npos) return ""; // 全空白返回空
              const size_t end = str.find_last_not_of(whitespace);
              return str.substr(start, end - start + 1);
          }
          
          int main() {
              // 待处理的多行文本
              std::string text = 
                  "nhello worldn"
                  "test target 123n"
                  "c++ regex demon"
                  "这是跨换行的内容n"
                  "foo target barn"
                  "no match heren";
              
              // 无 target 的跨行测试文本
              std::string textNoTarget = 
                  "nhello c++n"
                  "这是跨换行的内容n"
                  "无 target 字符串n";
          
              // 场景1:仅按行匹配(开启多行模式)
              std::cout << "=== 场景1:仅按行匹配(不跨换行)===" << std::endl;
              std::regex regex1("^(?!.*target).*$", std::regex_constants::multiline);
              std::sregex_iterator it1(text.begin(), text.end(), regex1);
              std::sregex_iterator end1;
              for (std::sregex_iterator i = it1; i != end1; ++i) {
                  std::string match = (*i).str();
                  std::string trimmed = trim(match);
                  if (!trimmed.empty()) {
                      std::cout << trimmed << std::endl;
                  }
              }
          
              // 场景2:跨换行匹配整段内容(开启 dotall 模式)
              std::cout << "n=== 场景2:跨换行匹配整段内容 ===" << std::endl;
              std::regex regex2("^(?!.*target).*$", std::regex_constants::dotall);
              bool isMatch = std::regex_match(text, regex2);
              if (!isMatch) {
                  std::cout << "整段文本包含 target,匹配失败" << std::endl;
              }
          
              // 匹配无 target 的文本
              bool isMatchNoTarget = std::regex_match(textNoTarget, regex2);
              if (isMatchNoTarget) {
                  std::cout << "n无 target 的跨行文本匹配结果:" << std::endl;
                  std::cout << trim(textNoTarget) << std::endl;
              }
          
              return 0;
          }
          

          编译运行命令

          # 编译(需支持 C++11 及以上)
          g++ regex_no_target.cpp -o regex_no_target -std=c++11
          # 运行
          ./regex_no_target

          运行结果

          === 场景1:仅按行匹配(不跨换行)===
          hello world
          c++ regex demo
          这是跨换行的内容
          no match here
          === 场景2:跨换行匹配整段内容 ===
          整段文本包含 target,匹配失败
          无 target 的跨行文本匹配结果:
          hello c++
          这是跨换行的内容
          无 target 字符串

          import re
          def main():
              # 待处理的多行文本(包含换行的跨行文内容)
              text = """
          hello world
          test target 123
          python regex demo
          这是跨换行的内容
          foo target bar
          no match here
              """
              # 场景1:仅按行匹配(不跨换行)
              print("=== 场景1:仅按行匹配(不跨换行)===")
              regex1 = r'^(?!.*target).*$'
              # 开启多行模式 re.M
              matches1 = re.findall(regex1, text, re.M)
              for match in matches1:
                  match = match.strip()
                  if match:
                      print(match)
              # 场景2:跨换行匹配整段内容(开启单行模式 re.S)
              print("n=== 场景2:跨换行匹配整段内容 ===")
              regex2 = r'^(?!.*target).*$'
              # 仅开启单行模式,匹配整段文本
              is_full_match = re.fullmatch(regex2, text, re.S) is not None
              if not is_full_match:
                  print("整段文本包含 target,匹配失败")
              # 测试无 target 的跨行文本
              text_no_target = """
          hello python
          这是跨换行的内容
          无 target 字符串
              """
              is_no_target_match = re.fullmatch(regex2, text_no_target, re.S) is not None
              if is_no_target_match:
                  print("n无 target 的跨行文本匹配结果:")
                  print(text_no_target.strip())
          if __name__ == "__main__":
              main()

          运行结果

          === 场景1:仅按行匹配(不跨换行)===
          hello world
          python regex demo
          这是跨换行的内容
          no match here
          
          === 场景2:跨换行匹配整段内容 ===
          整段文本包含 target,匹配失败
          
          无 target 的跨行文本匹配结果:
          hello python
          这是跨换行的内容
          无 target 字符串
          

          若需同时排除 target1 和 target2,只需叠加负向环视,核心模板如下:

          ^(?!.*target1)(?!.*target2).*$

          import re
          text = "test foo 123nhello bar 456npython demo 789"
          regex = r'^(?!.*foo)(?!.*bar).*$'
          matches = re.findall(regex, text, re.M)
          print([m.strip() for m in matches if m.strip()])  # 输出:['python demo 789']

          <?php
          $text = "test foo 123nhello bar 456nphp demo 789";
          $regex = '/^(?!.*foo)(?!.*bar).*$/m';
          preg_match_all($regex, $text, $matches);
          $result = array_filter(array_map('trim', $matches[0]));
          print_r($result); // 输出:Array ( [2] => php demo 789 )
          ?>

          运行结果

          Array
          (
              [2] => php demo 789
          )

          import java.util.regex.Matcher;
          import java.util.regex.Pattern;
          
          public class RegexExcludeMulti {
              public static void main(String[] args) {
                  String text = "test foo 123nhello bar 456njava demo 789";
                  String regex = "^(?!.*foo)(?!.*bar).*$";
                  Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
                  Matcher matcher = pattern.matcher(text);
                  
                  while (matcher.find()) {
                      String match = matcher.group().trim();
                      if (!match.isEmpty()) {
                          System.out.println(match); // 输出:java demo 789
                      }
                  }
              }
          }
          

          运行结果

          java demo 789

          package main
          
          import (
          	"fmt"
          	"regexp"
          	"strings"
          )
          
          func main() {
          	text := "test foo 123nhello bar 456ngolang demo 789"
          	regex := regexp.MustCompile(`(?m)^(?!.*foo)(?!.*bar).*$`)
          	matches := regex.FindAllString(text, -1)
          	
          	var result []string
          	for _, match := range matches {
          		trimmed := strings.TrimSpace(match)
          		if trimmed != "" {
          			result = append(result, trimmed)
          		}
          	}
          	fmt.Println(result) // 输出:[golang demo 789]
          }
          

          运行结果

          [golang demo 789]

          1. 排除多个字符串的核心逻辑是叠加多个负向环视断言,每个 (?!.*目标字符串) 对应一个需要排除的内容;
          2. 多语言实现时仅需保持正则核心不变,调整模式(如多行模式 m/(?m)/Pattern.MULTILINE)和匹配函数即可;
          3. 若需排除更多字符串(如 target3、target4),继续叠加 (?!.*target3)(?!.*target4) 即可,逻辑可无限扩展。

          若需按行匹配跨换行的文本(比如每行内容本身包含换行符),可同时开启两种模式:

          语言 模式开启方式(同时开启多行+单行) 示例正则
          PHP /ms /^(?!.target).$/ms
          Java Pattern.MULTILINE | Pattern.DOTALL Pattern.compile(“^(?!.target).$”, Pattern.MULTILINE | Pattern.DOTALL)
          Go (?ms) regexp.MustCompile(`(?ms)^(?!.target).$`)
          JavaScript /ms /^(?!.target).$/ms
          C++ std::regex_constants::multiline | std::regex_constants::dotall std::regex(“^(?!.target).$”, std::regex_constants::multiline | std::regex_constants::dotall)
          Python re.M | re.S re.findall(r’^(?!.target).$', text, re.M | re.S)

          1. 匹配“不包含指定字符串”的核心是负向环视 (?!...),基础模板为 ^(?!.*目标字符串).*$
          2. . 匹配换行符需开启单行模式:PHP /s、Java Pattern.DOTALL、Golang (?s)、JavaScript /s、C++ dotall、Python re.S;
          3. 多语言按行匹配需开启多行模式:PHP /m、Java Pattern.MULTILINE、Golang (?m)、JavaScript /m、C++ multiline、Python re.M;
          4. 排除多个字符串时,叠加多个负向环视断言即可,逻辑简单且易扩展;
          5. 不同语言的正则语法和标志略有差异,但核心原理相通,掌握一种后可快速迁移到其他语言。

          到此这篇关于正则表达式匹配不包含指定字符串的文本的文章就介绍到这了,更多相关正则表达式匹配不包含指定字符串内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • 正则表达式匹配不包含某些字符串的技巧
          • 正则表达式模式匹配字符串基础知识
          • js 正则表达式学习笔记之匹配字符串
          • java如何用正则表达式匹配与提取字符串
          • python正则表达式对字符串的查找匹配
          • Python 正则表达式匹配字符串中的http链接方法

          站内搜索