awk字段排序技术求助:按价格、里程、年份排序车辆数据
Hey there! Let's tackle this sorting problem with awk. First, let's quickly address why your original sort command didn't work—you had -k1,1b first, which sorts by the brand column before price/mileage/year, which is backwards from what you need. A fixed sort command would be sort -k5,5n -k4,4n -k3,3n, but since you asked for awk, let's dive into that.
First, here's your raw data for reference:
Toyota Camry 1999 120000 2000 Honda Civic 1990 100239 5000 Subaru Legacy 2003 72198 4300 Honda Accord 2008 80324 12839 Subaru WRX 2017 700 25000 Toyota Sienna 2005 75600 17832
Method 1: Composite Key Sorting (Simple & Efficient)
This approach creates a composite key from your sort fields (PRICE → MILEAGE → YEAR), stores each record against that key, then prints the records in sorted key order. We use sprintf to pad numeric values to fixed lengths so lexicographical sorting matches numeric sorting:
{ # Create a key that sorts first by PRICE, then MILEAGE, then YEAR # Padding ensures numbers like 2000 come before 5000 in lex order key = sprintf("%010d%010d%04d", $5, $4, $3) records[key] = $0 } END { # Iterate through sorted keys (awk sorts keys lex order by default) for (k in records) { print records[k] } }
Method 2: Custom Comparison Function (Flexible for Complex Rules)
If you want more control over the sorting logic (like easily switching between ascending/descending), use asorti with a custom comparison function. This stores each field separately, then sorts based on your priority:
# Store each record's details in arrays { idx++ full_record[idx] = $0 price[idx] = $5 mileage[idx] = $4 year[idx] = $3 } # Custom comparison: first compare price, then mileage, then year function sort_by_priority(i, j) { if (price[i] != price[j]) { return price[i] - price[j] # Ascending; reverse to price[j]-price[i] for descending } else if (mileage[i] != mileage[j]) { return mileage[i] - mileage[j] } else { return year[i] - year[j] } } END { # Sort the indices using our custom function asorti(full_record, sorted_indices, "sort_by_priority") # Print sorted records for (i in sorted_indices) { print full_record[sorted_indices[i]] } }
Expected Output (Ascending Order)
Running either script on your data will produce this sorted result:
Toyota Camry 1999 120000 2000 Subaru Legacy 2003 72198 4300 Honda Civic 1990 100239 5000 Honda Accord 2008 80324 12839 Toyota Sienna 2005 75600 17832 Subaru WRX 2017 700 25000
If you need descending order for any field, just flip the subtraction in the comparison function (e.g., return price[j] - price[i] for descending price).
内容的提问来源于stack exchange,提问作者Kevin Nguyen

