You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Shell/bash实现测试名与run-ksql-test结果的逐行映射

问题:Shell脚本实现测试名与测试结果的对应映射

前提

使用run-ksql-test工具,其输出格式见下文命令输出部分。现有测试文件,需将测试状态与测试名对应映射,且受DevOps限制只能使用Shell/bash实现。

测试文件格式

--@test: test Name 1
<multiple sql statements>
--@test: testName2
<multiple sql statements>
--@test: test Name3
<multiple sql statements>

命令输出

若干无特定格式且不含">>>"的行
[<timestamp>]: >>> Test Passed
若干无特定格式且不含">>>"的行
[<timestamp>]: >>> Test Passed
若干无特定格式且不含">>>"的行
[<timestamp>]: >>> Test Failed
若干无特定格式且不含">>>"的行

期望结果

--@test: test Name 1    [<timestamp>]: >>> Test Passed
--@test: testName2    [<timestamp>]: >>> Test Passed
--@test: test Name3    [<timestamp>]: >>> Test Failed 

需保留两边的完整行内容。

约束

  • 仅使用Shell代码,优先使用Linux/Unix默认工具(awk、grep、tr、cut、cat、sed等)。

现有问题

尝试的脚本会将带空格的测试名按单词拆分,无法得到期望格式,且未正确提取完整的测试结果行。现有代码片段如下:

do
    echo "---------------- TESTING $test_file ----------------"
    run-ksql-test --test-directory $test_file --temp-folder $TEMP_FOLDER  > $LOG_DIR/$(basename $test_file)
    
    #take Names Of the tests from assembled query file
    test_names=($(cat $test_file | grep -Eo  '\-\-\@.*'))  #also tried similar variations but outupt is either one chunk or broken into words 


    #take results from the logs for that file
    test_results=($(cat $LOG_DIR/$(basename $test_file) | grep -Eoi '>>>+(Passed|Failed)'))

    for ((i=0; i<${#test_names[@]}; i++)); do
        echo "${test_names[i]} ${test_results[i]}"
    done
    sleep 3

done

解决方案

方法1:使用awk关联处理(推荐)

用awk一次性处理测试文件和日志文件,将测试名存入数组,读取日志中的结果行后按顺序对应输出,无需处理Shell数组的空格拆分问题:

do
    echo "---------------- TESTING $test_file ----------------"
    run-ksql-test --test-directory "$test_file" --temp-folder "$TEMP_FOLDER" > "$LOG_DIR/$(basename "$test_file")"
    
    log_file="$LOG_DIR/$(basename "$test_file")"
    
    awk '
        BEGIN { idx=0; res_idx=0; }
        # 从测试文件提取完整测试名行
        FILENAME == ARGV[1] {
            if ($0 ~ /^--@test:/) {
                tests[++idx] = $0;
            }
            next;
        }
        # 从日志文件提取完整结果行
        FILENAME == ARGV[2] {
            if ($0 ~ /\[.*\]: >>> Test (Passed|Failed)/) {
                res[++res_idx] = $0;
            }
        }
        # 遍历输出对应关系
        END {
            for (i=1; i<=idx; i++) {
                printf "%-30s %s\n", tests[i], res[i];
            }
        }
    ' "$test_file" "$log_file"
    
    sleep 3
done

方法2:修复Shell数组读取逻辑

如果坚持用Shell数组,需修改IFS(内部字段分隔符)为换行,确保按整行读取测试名和结果,避免空格拆分:

do
    echo "---------------- TESTING $test_file ----------------"
    run-ksql-test --test-directory "$test_file" --temp-folder "$TEMP_FOLDER" > "$LOG_DIR/$(basename "$test_file")"
    
    log_file="$LOG_DIR/$(basename "$test_file")"
    
    # 按行读取测试名,禁用空格拆分
    IFS=$'\n' read -r -d '' -a test_names < <(grep -E '^--@test:' "$test_file")
    # 按行读取完整测试结果行
    IFS=$'\n' read -r -d '' -a test_results < <(grep -E '\[.*\]: >>> Test (Passed|Failed)' "$log_file")
    
    # 对应输出
    for ((i=0; i<${#test_names[@]}; i++)); do
        echo "${test_names[i]}    ${test_results[i]}"
    done
    
    sleep 3
done

关键说明

  • 所有文件路径用双引号包裹,避免文件名含空格时出错。
  • 方法1的awk实现更稳定,适合复杂文本处理场景;方法2直接修复原脚本的数组读取问题,逻辑更直观。

内容的提问来源于stack exchange,提问作者deepakmeena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:42:47