shannonredeemed

split()函数在使用中的特殊场景

前言

  split() 是Jmeter Java脚本组件中一个很方便实用的字符串分隔函数,但由于庞大的字符串家族丰富的多样性,导致一些子串在分隔时需要进行一些额外处理,我们一起来看一下吧~ 

踩坑之 split()函数按|分隔时,直接写成功split("|")是不可以的

1、上配置

(1)用户定义的变量 - 今日来练兵的主变量acctInfo

image

 

(2)线程组 - 默认配置就好喽

image

  

(3)JSR223取样器 - split函数示例

1 /*
2  * 前置组件中存在一个以字符串形式存储的变量 
acctInfo=["cod|id|typ|ip|ext|bak","03|62|2003|7107J|0|11000","02|85|3002|F107A|0|11000","03|37|2001|2107N|0|11000",
"01|96|6001|6564|3|11000"]
3 * 4 * 需求:获取acctInfo中的子串、将每个子串以|进行分割,然后遍历每个子串,并最终返回子串中第5项值为3的那个子串的第1项 5 * 6 */

image

image

(4)Java请求 - 打印处理过的变量值

image

(5)查看结果树 - 见前图就好咯~ 

image

2、看运行情况   

image

  没有报错,但是也没有获取到值。

3、分析请教

  item遍历完成了,但是cod没获取到,得,加代码,存储中间变量!

image

 image

  找到病灶了,这个子串的分割结果不正确……用|分隔字符串,难道不能写成split("|")吗?请Deep Seek来帮忙!

Shannon:
    Jmeter JSR223 组件,我用split("|")函数分割字符串"03|37|2001|2107N|0|11000",为什么得到的结果不是预期的['03','37','2001','2107N','0','11000']呢?


Deep Seek:
    在JMeter的JSR223组件中使用`split("|")`分割字符串没有得到预期结果,是因为**竖线`|`在正则表达式中有特殊含义(表示“或”关系)**,直接使用会导致错误分割。

下面表格汇总了核心原因和解决方案:

| 问题核心 | 错误示例 | 正确做法 | 原理说明 |
| :--- | :--- | :--- | :--- |
| **未转义特殊字符**`|` | `split("|")` | **
1. 双反斜杠转义:** `split("\\|")`  <br> **
2. 使用`Pattern.quote()`:** `split(Pattern.quote("|"))` | 正则引擎将`|`视为逻辑或,需转义为普通字符。 |

### 🔧 解决方案详解

在JSR223组件(推荐使用Groovy语言)中,您可以根据情况选择以下任一方法。

**方法一:双反斜杠转义**
直接在分割参数中使用`\\|`。
```groovy
// 您的字符串
String originalString = "03|37|2001|2107N|0|11000";
// 使用转义符进行分割
String[] parts = originalString.split("\\|");
// 将分割后的数组存入JMeter变量,方便后续使用
vars.putObject("splitParts", parts);
```

**方法二:使用Pattern.quote()**
如果分隔符不确定或有多个特殊字符,使用`Pattern.quote()`方法可以自动转义整个字符串。
```groovy
import java.util.regex.Pattern;
String originalString = "03|37|2001|2107N|0|11000";
// 使用Pattern.quote自动处理转义
String[] parts = originalString.split(Pattern.quote("|"));
vars.putObject("splitParts", parts);
```

### 💡 使用与验证分割结果

脚本执行后,可以通过以下方式验证和使用分割后的数组:

- **在JSR223组件中引用**:使用`vars.getObject("splitParts")`获取数组,并通过下标访问。
    ```groovy
    String[] myArray = vars.getObject("splitParts");
    log.info("第一个元素: " + myArray[0]); // 输出: 03
    ```

- **在JMeter其他元件中引用**:如果需要在如**HTTP请求**或**ForEach控制器**中使用,通常需要将数组元素转为单个JMeter变量。您可以在分割脚本后添加一个循环:
    ```groovy
    String[] parts = originalString.split("\\|");
    for (int i = 0; i < parts.size(); i++) {
        // 创建变量,例如 part_1, part_2...
        vars.put("part_" + (i + 1), parts[i]);
    }
    ```

### ⚠️ 温馨提示

- **语言选择**:确保JSR223组件的"Language"设置为"**groovy**",以获得更好的性能和对现代Java语法的支持。
- **变量获取**:在JSR223脚本中,应使用`vars.get()`和`vars.put()`来操作JMeter变量,避免直接使用`${variable}`的写法。
- **特殊字符**:除了竖线`|`,正则表达式中的特殊字符如点号`.`、星号`*`、加号`+`等,用作字面分隔符时也**需要同样进行转义**
当不确定时,`Pattern.quote()`是更稳妥的选择。 希望这些说明能帮助您解决问题。如果您在实现过程中遇到其他困难,欢迎随时追问。

4、调试解决

(1) 调试脚本 

  根据分析结果,修改脚本,并执行

image

image

  分隔结果看起来对了,但 cod 值不对,说明for循环体中的if判断没进去——改一下判断条件试试

image

image

  (2) 探索split() 函数需要 转义的其他字符

Shannon:
    这样需要转义的字符还有哪些呢?

Deep Seek:
    您问到了一个很关键的问题!以下是正则表达式中需要转义的特殊字符完整列表:

## 📋 正则表达式特殊字符全集

| 字符 | 名称 | 正则含义 | 转义写法 |
|------|------|----------|----------|
| `\` | 反斜杠 | 转义字符本身 | `\\\\` |
| `|` | 竖线 | 逻辑"或" | `\\|` |
| `.` | 点号 | 匹配任意字符 | `\\.` |
| `*` | 星号 | 前一个字符0次或多次 | `\\*` |
| `+` | 加号 | 前一个字符1次或多次 | `\\+` |
| `?` | 问号 | 前一个字符0次或1次 | `\\?` |
| `^` | 插入符 | 字符串开始位置 | `\\^` |
| `$` | 美元符 | 字符串结束位置 | `\\$` |
| `()` | 圆括号 | 分组捕获 | `\\(\\)` |
| `[]` | 方括号 | 字符类 | `\\[\\]` |
| `{}` | 花括号 | 量词范围 | `\\{\\}` |

## 🎯 实用记忆口诀

**"点星加问,^$杠竖,括号花方,统统要转"**

## 🔧 在JMeter JSR223中的实际应用

### 常见分隔符的转义示例:

```groovy
// 1. 竖线分隔:03|37|2001
String[] result1 = "03|37|2001".split("\\|");

// 2. 点号分隔:192.168.1.1
String[] result2 = "192.168.1.1".split("\\.");

// 3. 星号分隔:A*B*C
String[] result3 = "A*B*C".split("\\*");

// 4. 问号分隔:what?why?how
String[] result4 = "what?why?how".split("\\?");

// 5. 加号分隔:1+2+3
String[] result5 = "1+2+3".split("\\+");

// 6. 多个特殊字符:A.B|C*D
String[] result6 = "A.B|C*D".split("\\.\\|\\*");  // 复杂情况
```

### 💡 更安全的做法:使用 `Pattern.quote()`

当您不确定分隔符是否包含特殊字符,或者分隔符是动态变量时,推荐使用:

```groovy
import java.util.regex.Pattern;

String delimiter = "|";  // 可能是用户输入或变量
String text = "03|37|2001";

// 自动处理所有转义
String[] parts = text.split(Pattern.quote(delimiter));
```

### 🚀 高级技巧:处理多个可能的分隔符

```groovy
// 如果可能有多种分隔符,比如 | 或 , 或 ;
String text = "A|B,C;D";
String[] parts = text.split("[|,;]");  // 字符类中的 | 不需要转义

// 或者分别处理
String[] parts2 = text.split("\\||,|;");
```

## ⚠️ 重要提醒

1. **反斜杠需要双重转义**:在Java/Groovy字符串中,`\` 本身需要转义,所以 `\` 变成 `\\\\`

2. **字符类中的例外**:在方括号 `[]` 内,大多数特殊字符失去特殊含义,但 `^`、`-`、`]`、`\` 仍需注意

3. **最佳实践**:当分隔符来自用户输入或配置时,**总是使用 `Pattern.quote()`**

```groovy
// 安全做法
String userDelimiter = vars.get("delimiter");  // 从JMeter变量获取
String[] safeParts = originalString.split(Pattern.quote(userDelimiter));
```

记住这个列表和 `Pattern.quote()` 方法,您就能轻松应对所有分隔符转义问题了!

  看了这个表格,却是清晰多了!

 

 

总结 

  这篇博客的重点可以说是非常清晰了:字符串分割函数split(""),在处理一些按特定字符(比如\, |, ., $,?,+等)进行分割时,需要对相应的字符进行转义,比如split("\\\\"), split("\\|"), split("\\?"), split("\\+"), split("\\.")等等,理由参见上文,不再赘述。

  在调试今天的博客脚本时,其实还有如下没被突出强调的小细节,这里一并记录:

  1. vars.put("acctInfoArray", acctInfoArray) 需要写成 vars.put("acctInfoArray", acctInfoArray.toString()) 才能正常存储,这个前面的博客其实是说过的

  2. 在判断分割后的子串中的第5项值是否为3时,用==是不好使的,需要用itemArray[4].equals("3"),再一次验证了字符串比较函数的使用

 

  呛呛!~ 本篇博客就到这里了!~ 最近读完了《纳瓦尔宝典》的前半部分——关于财富与致富的方法,很感人,受了些启发,但落地之路并不会轻而易举,尤其是当大家对财富有不同的定义时……

  最近跟朋友聊天,朋友也认为“致富”是生活第一要义,可是这个观念从来没有占据过我的思想高地,所以我觉得有些隔膜,但我不能否定是因为自己刻意回避了一些现实和自己的弱项才导致今天的价值观,怯怯地跟朋友说起这个,朋友回复了一句:“大师,你把你教我的做好了,就可以坐享其成了……” ——这里的上文是,我先跟朋友分享了一个工作方法:【在每日清单上面去工作,把优先次序安排好,在自己的轨道上奔跑,要把自己的精力时间投放在自己的强项上,只要发挥了强项,没有干不成的事儿,自信会给人带来强大的力量,需要专注,不能分散注意力。】

  再看一遍这句话,发现清单不是这里的唯一重点,还有更重要、更需要思考的:我的强项,是什么? 

下期预告

   下一篇博客,我们将一起看一下如何进行测试结果的文件输出,这会是一个很实用的功能。一起期待一下吧!

posted on 2025-09-28 17:36  Shannon_Zhang  阅读(17)  评论(0)    收藏  举报