Vergleichen Sie zwei Dateien. Wenn die Spalten gleich sind, ersetzen Sie die nächste Spalte durch einen Wert.

Vergleichen Sie zwei Dateien. Wenn die Spalten gleich sind, ersetzen Sie die nächste Spalte durch einen Wert.

Wie ersetze ich einen Spaltenwert in einer Datei beim Vergleich mit einer anderen Datei?

Ich habe zwei Dateientest1.csvUndtest2.csv; Ich muss die empdepSpalte ersetzen intest1.csvwenn es den Wert hat als"Zeichen*"Die zweite Dateitest2.csvhat den nötigen Wert, um das zu ersetzen"Zeichen*".

Hinweis: Ich verwende kshundtest1.csvhat rund 2.048.576 Zeilen undtest2.csvhat 10.000 Zeilen.

test1.csv

empname,place,empdep
aaaa,city1,001
bbbb,city2,sign-1
dddd,city1,005
ffff,city5,sign-2
hhhh,city7,sign-1

test2.csv

empname,new
aaaa,001
bbbb,002
cccc,003
dddd,005
eeee,006
ffff,007
gggg,008
hhhh,009

Erwartetes Ergebnis:

empname,place,empdep
aaaa,city1,001
bbbb,city2,002
dddd,city1,005
ffff,city5,007
hhhh,city7,009

Antwort1

Mit awk:

awk '
  BEGIN{ FS=OFS="," } # set input/output field separator to `,`
  NR==FNR{            # if this is the first file `test2.csv`
    a[$1]=$2          # store field2 in array `a` using field1 as index
    next              # continue with next line
  } 
  $3 ~ /^sign/{       # if field3 of `test1.csv` begins with `sign`
    $3=a[$1]          # replace the field with array value (index of field1)
  }
  1                   # print the line
' test2.csv test1.csv

Antwort2

Dies ist eine einfache Möglichkeit:

for i in $(cat text1.csv)  
do  
    name=$(echo $i | cut -d',' -f1)   
    empdep=$(echo $i | cut -d',' -f3)  
    newvalue=$(grep $name text2.csv | cut -d',' -f2)    
    if [[ $empdep = sign* ]]    
    then  
        sed -n "s/^$name,\(.*\),.*/$name,\1,$newvalue/pg" text1.csv  
    else  
        echo $i  
    fi  
done

Antwort3

Verwenden Sie kshund sed. Verwenden Sie sedzum Parsentest2.csvund bevölkern Sie eineassoziatives Array ${new[@]}. Dann durchlaufentest1.csvund VerwendungMustersubstitutionum die gewünschten Ausgaben auszudrucken:

typeset -A new $(sed -n '2,${s/^/new[/;s/,/]=/p}' test2.csv)
while IFS=, read a b c; do echo $a,$b,${c/#sign*/${new[$a]}}; done < test1.csv

Ausgabe:

empname,place,empdep
aaaa,city1,001
bbbb,city2,002
dddd,city1,005
ffff,city5,007
hhhh,city7,009

Hinweis: In diesem Fall haben die Eingabedateien keine Anführungszeichen und der Code ist ohne Anführungszeichen optisch einfacher. Wenn eine der Eingabedateien Leerzeichen enthält (oder enthalten könnte), werden die oben genannten Variablenmusszitiert werden.

Antwort4

csv-merge -N t1 -p test1.csv -N t2 -p test2.csv | 
csv-sqlite -T 'select t1.empname, t1.place, case when t1.empdep like "sign%" then t2.new else t1.empdep end as empdep
from t1 left join t2 on t1.empname = t2.empname'

csv-merge und csv-sqlite sind vonhttps://github.com/mslusarz/csv-nix-tools

verwandte Informationen