Как прочитать CSV-файл в массивы и сравнить и заменить его записями из другого CSV-файла? - PullRequest
0 голосов
/ 21 января 2019

У меня есть два файла CSV file1.csv и file2.csv.
file1.csv содержит 4 столбца.

file1:

Header1,Header2,Header3,Header4
aaaaaaa,bbbbbbb,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
iiiiiii,jjjjjjj,kkkkkkk,lllllll
mmmmmmm,nnnnnnn,ooooooo,ppppppp

file2:

"Header1","Header2","Header3"
"aaaaaaa","cat","dog"
"iiiiiii","doctor","engineer"
"mmmmmmm","sky","blue"

Итак, что я пытаюсь сделать, это читать file1.csv построчно, помещать каждую запись в массив, затем сравнивать первый элемент этого массива с первым столбцом file2.csv и, если совпадение существует, заменить столбец1и column2 файла file1.csv с соответствующим столбцом file2.csv

Итак, мой желаемый вывод:

cat,dog,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
doctor,engineer,kkkkkkk,lllllll
sky,blue,ooooooo,ppppppp

Я могу сделать это, когда есть только столбец для замены.
Вот мой код:

awk -F'"(,")?' '
NR==FNR { r[$2] = $3; next }
{ for (n in r) gsub(n,r[n]) } IGNORECASE=1' file2.csv file1.csv>output.csv

Мой последний шаг - выгрузить весь массив в файл с 10 столбцами.Любые предложения, где я могу улучшить или исправить свой код?

Ответы [ 3 ]

0 голосов
/ 21 января 2019

Учитывая ваши примерные данные и описание из ваших комментариев, попробуйте следующее:
(Судя по вашему собственному коду, у вас могут быть кавычки вокруг полей, поэтому я не пытался ответить.)

awk 'BEGIN{FS=OFS=","}
    NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");a[$1]=$2;b[$1]=$3;next}
    $1 in a{$2=b[$1];$1=a[$1];}
    1' file2.csv file1.csv

Например:

$ cat file1.csv
Header1,Header2,Header3,Header4
aaaaaaa,bbbbbbb,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
iiiiiii,jjjjjjj,kkkkkkk,lllllll
mmmmmmm,nnnnnnn,ooooooo,ppppppp

$ cat file2.csv
"Header1","Header2","Header3"
"aaaaaaa","cat","dog"
"iiiiiii","doctor","engineer"
"mmmmmmm","sky","blue"

$ awk 'BEGIN{FS=OFS=","}
NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");a[$1]=$2;b[$1]=$3;next}
$1 in a{$2=b[$1];$1=a[$1];}
1' file2.csv file1.csv
Header2,Header3,Header3,Header4
cat,dog,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
doctor,engineer,kkkkkkk,lllllll
sky,blue,ooooooo,ppppppp

Другой способ, более подробный, но я думаю, что вам лучше понять (GNU awk):

awk 'BEGIN{FS=OFS=","}
    NR==FNR{for(i=1;i<=NF;i++)$i=gensub(/^"(.*)"$/,"\\1",1,$i);a[$1]=$2;b[$1]=$3;next}
    $1 in b{$2=b[$1];}
    $1 in a{$1=a[$1];}
    1' file2.csv file1.csv

Обратите внимание на ловушку здесь,поскольку $1 является ключом, поэтому мы должны изменить $1 last.

Решение без учета регистра:

awk 'BEGIN{FS=OFS=","}
    NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");k=tolower($1);a[k]=$2;b[k]=$3;next}
    {k=tolower($1);if(a[k]){$2=b[k];$1=a[k]}}
    1' file2.csv file1.csv

Для краткого кода добавлено variabe k и перемещено "if" внутри.

0 голосов
/ 21 января 2019

С любым awk и любым количеством полей в любом файле:

$ cat tst.awk
BEGIN { FS=OFS="," }
{
    gsub(/"/,"")
    key = tolower($1)
}
NR==FNR {
    for (i=2; i<=NF; i++) {
        map[key,i] = $i
    }
    next
}
{
    for (i=2; i<=NF; i++) {
        $(i-1) = ((key,i) in map ? map[key,i] : $(i-1))
    }
    print
}

$ awk -f tst.awk file2 file1
Header2,Header3,Header3,Header4
cat,dog,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
doctor,engineer,kkkkkkk,lllllll
sky,blue,ooooooo,ppppppp
0 голосов
/ 21 января 2019

РЕДАКТИРОВАТЬ: Учитывая, что ваш Input_file2 имеет дату в формате "ytest","test2" и т. Д., Если да, попробуйте выполнить следующее. (Спасибо Tiw за предоставленные образцы в его / ее посте)

awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  gsub(/\"/,"")
  a[tolower($1)]=$0
  next
}
a[tolower($1)]{
  print a[tolower($1)],$NF
  next
}
1' file2.csv file1.csv


Не могли бы вы попытаться выполнить следующие действия.

awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  a[$1]=$0
  next
}
a[$1]{
  print a[$1],$NF
  next
}
1'  Input_file2  Input_file1

ИЛИ, если у вас может быть комбинация строчных и заглавных букв во входных файлах, то попробуйте выполнить следующее.

awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  a[tolower($1)]=$0
  next
}
a[tolower($1)]{
  print a[tolower($1)],$NF
  next
}
1'  Input_file2  Input_file1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...