
Я хочу сравнить два файла с одинаковым количеством строк и столбцов с записями в том же порядке. Просто хочу выделить различия в значениях столбцов, если таковые имеются.
file A
:
1,kolkata,19,ab
2,delhi,89,cd
3,bangalore,56,ef
file B
:
1,kolkata,21,ab
2,mumbai,89,gh
3,bangalore,11,kl
Рассматривая столбец 1
как первичный ключ, у нас есть различия в других столбцах. Я хочу подчеркнуть эти различия.
Формат вывода может быть (не уверен):
record_number, columns_with_diff
1 3
2 2,4
3 3,4
Может ли diff
или comm
решить мою проблему? Если да, то какая будет точная команда?
решение1
Вот это да. Просто какая-то проблема со стилем, с дополнительной запятой в конце каждой строки.
awk '
BEGIN{ FS=","; ORS="" }
{
# read line from secondary file
getline aux < "file2"
split(aux,f2,",")
# print current line number
print NR" "
# process each field in current line
for(i=1; i<=NF; i++) {
if ($i!=f2[i]) {
print i","
}
}
print "\n"
}
' file1
Выход:
1 3,
2 2,4,
3 3,4,
решение2
Вы можете сделать это проще с помощью perl
:
$ perl -F',' -anle '
BEGIN{
print "record_number, columns_with_diff";
$" = ",";
}
if (!defined($h{$.})) {
@{$h{$.}}{0..$#F} = @F[0..$#F];
} else {
@diff = grep { $h{$.}{$_} ne $F[$_] } 0..$#F;
print "$.\t\t@{[map {$_+1} @diff]}";
}
close ARGV if eof;
' file1 file2
record_number, columns_with_diff
1 3
2 2,4
3 3,4
Для этого вам следует удалить пустые строки из входных данных.
Объяснение
В
BEGIN
блоке мы просто печатаем заголовок вывода, затем устанавливаем разделитель списка на,
@{$h{$.}}{0..$#F} = @F[0..$#F]
: мы создаем хеш хешей, где ключами первого хеша являются номера строк, ключами каждого подхеша являются индексы полей минус 1, а значениями являются значения, соответствующие этим полям.
Здесь мы используем хэш-срез для быстрого присвоения значений хэшу хэшей.
если вы используете Data::Dumper
для печати хэш хэшей %h
, вы можете увидеть что-то вроде этого:
VAR1 = {
'2' => {
'2' => '89',
'0' => '2',
'1' => 'delhi',
'3' => 'cd'
},
'3' => {
'1' => 'bangalore',
'3' => 'ef',
'0' => '3',
'2' => '56'
},
'1' => {
'3' => 'ab',
'1' => 'kolkata',
'0' => '1',
'2' => '19'
}
};
Если мы создали
%h
(if (!defined($h{$.}))
) - то есть завершили обработкуfile1
- мы просто сравниваем каждое поле текущей строки с соответствующим значением в%h
, сохраняя все индексы, которые отличаются, в массиве@diff
.map {$_+1} @diff
Восстанавливаем номер столбца, поскольку индекс массива начинается с 0, номер столбца начинается с 1.close ARGV if eof
восстановить$.
счетчик.