使用Shell脚本根据匹配值更新文件列的需求及代码问题
Fixing Your KSH Script for Merging Files A and B
First, let's break down what's not working in your original script:
- Incorrect variable assignment: Lines like
var1 =$18are invalid—you can't have spaces around=, and$18doesn't refer to the first column of the current line. To extract columns from a line, you should split the line into variables when reading it (e.g.,read col1 col2 col3 <<< "$line"). - Inefficient nested loops: Reading file B every time you process a line from file A is slow and unnecessary.
- Wrong command usage: The
mvcommand moves files—this isn't how you modify the content of lines to build a new file. - Syntax errors in conditionals:
[$var1==$var3]is missing spaces around[and], and in ksh, you should use=instead of==for string comparison (or use[[ ]]for safer checks).
Best Solution: Use AWK (Efficient & Clean)
AWK is designed exactly for this kind of text processing task. Here's a script that will generate your desired file C:
cd /test/files awk ' # Process file B (cde.dat) first: store its first two columns as a key, third as value NR == FNR { map[$1,$2] = $3 next } # Now process file A (abc.dat) { # Check if the first two columns exist in our map if (($1,$2) in map) { print $1, $2, map[$1,$2] } else { print $0 # Keep original line if no match } } ' cde.dat abc.dat > fileC.dat
How This Works:
NR == FNR: This condition is true only when we're reading the first input file (cde.dat). We use a 2-dimensional arraymapto store the third column value, indexed by the first two columns combined.- For each line in
abc.dat, we check if the first two columns exist as a key inmap. If yes, we print the first two columns plus the value frommap; if not, we print the original line. - The output is redirected to
fileC.dat(your desired file C).
Alternative: Pure KSH Script
If you need to stick to ksh (note: this requires ksh93 or newer for associative arrays), here's a working version:
cd /test/files # Create an associative array to store data from file B typeset -A b_data # Populate the array with file B's content: key = "col1 col2", value = col3 while read col1 col2 col3; do b_data["$col1 $col2"]="$col3" done < cde.dat # Process file A to build file C while read col1 col2 col3; do key="$col1 $col2" # Check if the key exists in our array if [[ -n "${b_data[$key]}" ]]; then echo "$col1 $col2 ${b_data[$key]}" else echo "$col1 $col2 $col3" fi done < abc.dat > fileC.dat
How This Works:
- We first read all lines from
cde.datinto an associative array where each key is the first two columns (joined by a space) and the value is the third column. - We then iterate over each line in
abc.dat, check if the key exists in the array, and print either the modified line (with file B's third column) or the original line.
Both scripts will produce your desired file C:
111 Apple Blue 112 Orange Black 113 Mango Yellow
内容的提问来源于stack exchange,提问作者ganesh_patil
相关产品推荐
相关产品推荐

