Bash数组sort语句异常排查及脚本优化咨询
Hey there, let's work through your Bash script issues step by step! I'll help you figure out why your second sort isn't running, plus share some solid optimization tips for your messy script.
一、Why Your Second sort Isn't Executing (No Errors)
First off, let's look at your array initialization line: testarr1=[]; — this is invalid in Bash. To declare an empty array, you need to use testarr1=(). If you're trying to run sort on this malformed array, there's no actual content for sort to process, which is why it's silently failing without errors.
If your second sort is meant to handle the testarr1 array later, here's the correct way to set it up and sort:
# Correct empty array declaration testarr1=() # Once testarr1 has content, sort it IFS=$'\n' sorted_testarr1=($(sort <<<"${testarr1[*]}")) unset IFS
If the second sort is supposed to process data from your while read loop (like the digit0 array), make sure you're passing the array content to sort properly. For example:
# Sort the digit0 array from your CSV line IFS=$'\n' sorted_digit0=($(sort <<<"${digit0[*]}")) unset IFS
二、Script Optimization Tips
Since you mentioned your script is messy, here are actionable ways to clean it up and make it more robust:
1. Fix Array & Variable Initialization
- Always use
testarr1=()for empty arrays —testarr1=[]creates an array with a single string element[], which is almost never what you want. - Initialize variables right before you need them (e.g., move
cou0=0just above thewhileloop) to avoid cluttering the global scope.
2. Localize IFS Changes
Your current approach of IFS=$'\n' ... unset IFS modifies the global IFS value, which can break other commands later. Instead, contain the IFS change to a local scope:
# Use a subshell to isolate IFS (no need to unset) sorted_testarr00=$(IFS=$'\n'; sort <<<"${testarr0[*]}") # Or use parentheses to create a local block ( IFS=$'\n' testarr00=($(sort <<<"${testarr0[*]}")) # Changes to IFS here won't affect the rest of the script )
3. Simplify Nested Loops
Nested while + for loops can get messy and slow. For CSV processing (like your ticket0 lines), consider using awk to handle splitting and sorting in one go, which is more efficient:
# Example: Sort CSV lines by the first column (numeric) awk -F',' '{print $0}' "$input" | sort -t',' -k1,1n
4. Modularize Reusable Logic
Turn repeated tasks (like sorting arrays) into functions. This makes your script easier to read and maintain:
# Function to sort an array numerically sort_array() { local arr=("$@") local sorted_arr IFS=$'\n' sorted_arr=($(sort -n <<<"${arr[*]}")) unset IFS echo "${sorted_arr[@]}" } # Use the function like this testarr00=($(sort_array "${testarr0[@]}"))
5. Add Error Handling & Debugging
Catch silent failures and debug issues faster with these strict mode settings at the top of your script:
#!/bin/bash set -euo pipefail # Exit on error, unset variable error, and pipe failures set -x # Optional: Print every command as it runs (great for debugging)
Optimized Script Snippet Example
Here's how your script could look with these fixes applied:
#!/bin/bash set -euo pipefail # Target ticket array testarr0=(37 32 11 31 41 10) # Empty array initialized correctly testarr1=() # Reusable array sorting function sort_array() { local arr=("$@") local sorted_arr IFS=$'\n' sorted_arr=($(sort -n <<<"${arr[*]}")) unset IFS echo "${sorted_arr[@]}" } # Sort the target ticket array testarr00=($(sort_array "${testarr0[@]}")) cou0=0 input="test_tickets0" # Process each line in the ticket file while IFS= read -r ticket0; do # Split CSV line into an array IFS=',' read -ra digit0 <<< "$ticket0" # Sort the digit array if needed sorted_digit0=($(sort_array "${digit0[@]}")) # Add your processing logic here... ((cou0++)) done < "$input"
内容的提问来源于stack exchange,提问作者calmchess

