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

Bash脚本调用外部脚本时循环迭代跳过问题排查求助

Bash循环调用脚本时部分迭代未执行的问题解决

问题描述

我编写了一个Bash脚本,从CSV文件第一列读取参数并循环调用testing.sh脚本,但部分循环迭代未执行:仅在循环内打印element时能输出所有项,一旦执行testing.sh,对应的echo语句就不再打印,推测问题与调用testing.sh的方式有关。

主脚本代码:

code_sections_file="code_sections.csv"
script="testing.sh"
pwd
awk -F "," '{print $1}' "$code_sections_file" | while IFS= read -r element; do
    echo "======= $element ========"
    ./testing.sh "$element"
done

testing.sh脚本代码:

#!/bin/bash

file_non_compile=()

#============================== CSV Structure ====================================
# Bug Name, Example Name, Example Path, Starting Line, Ending Line
#=================================================================================

code_sections_file="code_sections.csv"

# ---------------------------- Preprocessing input -------------------------------
result="$1"
result_line=$(grep "^$result," "$code_sections_file")
IFS="," read -ra info_array <<< $result_line

bug="${info_array[0]}"
example_name="${info_array[1]}"
example_path="${info_array[2]}"
first_line="${info_array[3]}"
second_line="${info_array[4]}" 

# ------------------------------ Directory Paths ----------------------------------
error_path="../testlogs/noncompiled/$bug"
code_folder="nvml/src/examples/libpmemobj/$example_path"   # nvml/src/examples/libpmemobj/$example_path - Path to the file
original_folder="../original/$example_path"                # ../original/$example_path - Path to the original state of the file
buged_folder="../buged/$example_path"                      # ../buged/$example_path - Path to the bugged state of the file
patch_path="./patch/$example_name/$bug.patch"              # ./patch/$example_path{-.c+patch} - file with the buggy patch
IFS='/'
read -ra patharr <<< "$example_path"
testlogs_path="../testlogs/${patharr[0]}/$bug"             # ../testlogs/$example_path.split("/")[0]/$bug_(prompt_eng_tech).txt - file with logs
results="../masterThesis/Results"                         # ../masterThesis/Results/{prompt}/{$bug.txt} 

echo "$patch_path"
echo "$bug $example_name $example_path $first_line $second_line"

# ==================================================================================

# Copy original code file to a folder
cp $code_folder $original_folder
sleep 10

# ===================================== Bug ========================================

echo "=========== $bug ============="
sleep 5


# Apply the patch bug
echo "Applying the bug patch..."
./patch/patch.sh ./ $patch_path
sleep 2

# Copy buggy file to a folder
cp $code_folder $buged_folder
echo "Done."
sleep 10

# Build the examples
echo "Compiling the code..."
make nvml-example &> /dev/null
if [ $? -ne 0 ]; then
    echo " ========== Make failed =============== "
    file_non_compile+(" ")
    read
fi
echo "Done."
sleep 4

# Execute program and save log to file.
echo "Executing the buggy program..."
sudo make nvml-exec arg=$example_name > ../testlogs/$example_name/$bug.txt
echo "Done. Output saved to ../testlogs/$example_name/$bug.txt"
sleep 2

# ======================================================================================

verify_correction() {
    current_strategy=$1
    echo $current_strategy
    echo "Writing bug correction..."
    prev_line=$((first_line - 1))
    sed "${first_line},${second_line}d" $code_folder > ../temp.txt && sed -n -e "/\`\`\` \?C/,/\`\`\`/p" -e "/''' \?C/,/'''/p" $results/$current_strategy/$bug.txt | sed '1d;$d' | sed "${prev_line}r /dev/stdin" ../temp.txt > ../temp2.txt && mv ../temp2.txt ../temp.txt

    #sed '180,239d' nvml/src/examples/libpmemobj/hashmap/hashmap_tx.c > ../temp.txt && sed '4,57!d' ../mastersThesis/Results/ZeroShot/hashmap_tx_backup_3.txt | sed '179r /dev/stdin' ../temp.txt > ../temp2.txt && mv ../temp2.txt ../temp.txt
    # Write temp file content to original file
    cp ../temp.txt $code_folder
    echo "Done."

    # Rebuild Examples
    echo "Compiling code..."
    make nvml-example &> /dev/null
    if [ $? -ne 0 ]; then
    echo " ========== Make failed =============== "
        file_non_compile+("$bug\_$1")
        read
    fi
echo "Done."
sleep 4

    # Execute "repaired" program and save to logs
    echo "Executing program with Zero-Shot correction..."
    sudo make nvml-exec arg=$example_name > ../testlogs/$example_name/$bug\_$2.txt
    echo "Done. Output saved to ../testlogs/$example_name/$bug\_$2.txt"

    # Return buggy code
    echo "Reverting to buggy code and recompiling..."
    cp ../buged/$example_path $code_folder
    make nvml-example &> /dev/null
    echo "Done."
sleep 2
}

# ================================= Zero-Shot Learning =================================

verify_correction "ZeroShot" "Zero"
verify_correction "ZeroShotCoT" "ZeroCoT"
verify_correction "MoreExamples/FewShot" "Two"
verify_correction "MoreExamples/FewShotCoT" "TwoCoT"
verify_correction "OneExample/FewShot" "One"
verify_correction "OneExample/FewShotCoT" "OneCoT"

echo "Reset code sample..."
./patch/patch.sh -R ./ $patch_path
sleep 2
echo "Done."

echo "The following corrections did not compile:"
if [ ${#file_non_compile[@]} -gt 0 ]; then
    for file in "${file_non_compile[@]}"; do
        echo "$file" >> "$error_path"
    done
fi

echo "All verifications done for bug $bug."
echo "Results can be found in ../testlogs/$example_name/ folder."

问题原因

核心问题是管道的标准输入被testing.sh中的read命令消耗。外层循环通过awk ... | while read ...的管道方式获取输入,管道的stdin会被循环内执行的testing.sh共享。而testing.sh里有多处单独的read命令(比如编译失败时的暂停操作),这些命令会读取管道中剩余的内容,导致外层while read提前结束,后续迭代无法执行。

解决方案

方案1:修改testing.sh中的read命令

testing.sh里的read只是用来暂停脚本,不需要读取管道内容。将所有单独的read替换为:

# 读取一个字符但不从stdin获取,避免消耗管道内容
read -n 1 < /dev/null
# 或者直接用sleep替代(如果不需要等待用户按键)
# sleep 5

方案2:重构外层循环,避免使用管道

用进程替换替代管道,让while read的stdin独立于子进程:

code_sections_file="code_sections.csv"
script="testing.sh"
pwd
while IFS= read -r element; do
    echo "======= $element ========"
    ./testing.sh "$element"
done < <(awk -F "," '{print $1}' "$code_sections_file")

方案3:使用临时文件存储awk输出

先把awk的结果写入临时文件,再循环读取:

code_sections_file="code_sections.csv"
script="testing.sh"
pwd
tmpfile=$(mktemp)
awk -F "," '{print $1}' "$code_sections_file" > "$tmpfile"
while IFS= read -r element; do
    echo "======= $element ========"
    ./testing.sh "$element"
done < "$tmpfile"
rm "$tmpfile"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:12:32