Я использую Solaris 10, поэтому параметры grep, включающие -f, не работают.
У меня есть два файла, разделенных каналом:
file1:
abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|
файл 2:
abc|123|
kumar|pki|
cab|234
Я хотел бы сравнить первые два столбца файла file2 с файлом file1 (поиск по всему содержимому файла file1 в первых двух столбцах), если они совпадают, вывести соответствующую строку файла file1. Затем найдите вторую строку файла 2 и так далее.
Ожидаемый результат:
abc|123|BNY|apple|
cab|234|cyx|orange|
У меня огромные файлы, содержащие около 400 000 строк, поэтому я хотел бы ускорить их выполнение.
shell-script
text-processing
perl
user68365
источник
источник
grep
, она под/usr/sfw/bin/ggrep
. stackoverflow.com/questions/15259882/…Ответы:
Вот для чего был разработан awk:
объяснение
-F'|'
: устанавливает разделитель полей в|
.NR==FNR
: NR - номер текущей строки ввода, а FNR - номер строки текущего файла. Два будут равны только во время чтения 1-го файла.c[$1$2]++; next
: если это первый файл, сохраните первые два поля вc
массиве. Затем перейдите к следующей строке, чтобы она применялась только к 1-му файлу.c[$1$2]>0
: блок else будет выполняться, только если это второй файл, поэтому мы проверяем, были ли уже видны поля 1 и 2 этого файла (c[$1$2]>0
), и если они были, мы печатаем строку. Вawk
, действие по умолчанию состоит в том, чтобы напечатать строку, поэтому, если значениеc[$1$2]>0
равно true, строка будет напечатана.Кроме того, поскольку вы пометили с помощью Perl:
объяснение
Откроется первая строка
file2
, прочитайте все, вплоть до 2nd|
(.+?\|[^|]+
), и сохраните это ($&
результат последнего оператора соответствия) в%k
хэше.Вторая строка обрабатывает file1, использует одно и то же регулярное выражение для извлечения первых двух столбцов и печатает строку, если эти столбцы определены в
%k
хэше.Оба вышеупомянутых подхода должны будут содержать 2 первых столбца файла 2 в памяти. Это не должно быть проблемой, если у вас есть только несколько сотен тысяч строк, но если это так, вы можете сделать что-то вроде
Но это будет медленнее.
источник
file2
в память?awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0'
это более короткая версия.file2
есть ли повторяющиеся строки?я думаю
это то, что вы ищете. Это должно быть эффективно, но я не уверен, что это будет так точно, как вы хотите. Если
abc|123
(например) найти в строкеfile1
в разных столбцах, эта строка будет напечатана. Если вы можете гарантировать, что этого никогда не произойдет, вышеприведенная строка должна работать.источник
Если вы хотите думать о проблеме в SQL как-то иначе, то вам определенно стоит попробовать инструмент с именем ' q ':
Это более понятно и легко понять, если вы знакомы с запросами SQL.
источник
источник