Как извлечь общие строки из нескольких файлов?
У меня есть 15 различных файлов, которые я хочу иметь новый файл, который включает только общие строки во всех них. например:
File1:
id1
id2
id3
file2:
id2
id3
id4
file3:
id10
id2
id3
file4
id100
id45
id3
id2
I need the output be like:
newfile:
id2
id3
Я знаю, что эта команда работает для каждой пары файлов:
grep -w -f file1 file2> output
но мне нужна команда для работы более чем на 2 файла.
Любое предложение, пожалуйста?
4 ответа
Используя grep
Один и тот же трюк можно использовать более одного раза:
$ grep -w -f file1 file2 | grep -w -f file3 | grep -w -f file4
id2
id3
Кстати, если вы ищете точные совпадения, а не совпадения с регулярным выражением, лучше и быстрее использовать -F
флаг:
$ grep -wFf file1 file2 | grep -wFf file3 | grep -wFf file4
id2
id3
Использование awk
$ awk 'FNR==1{nfiles++; delete fseen} !($0 in fseen){fseen[$0]++; seen[$0]++} END{for (key in seen) if (seen[key]==nfiles) print key}' file1 file2 file3 file4
id3
id2
FNR==1{nfiles++; delete fseen}
Каждый раз, когда мы начинаем читать новый файл, мы делаем две вещи: (1) увеличиваем счетчик файлов,
nfiles
, и (2) удалить массивfseen
,!($0 in fseen){fseen[$0]; seen[$0]++}
Если текущая строка не является ключом в
fseen
затем добавьте его вfseen
и увеличить счетчик для этой строки вseen
,END{for (key in seen) if (seen[key]==nfiles) print key}
После того, как мы прочитали последнюю строку последнего файла, мы смотрим на каждый ключ в
seen
, Если количество для этого ключа равно числу файлов, которые мы прочитали,nfiles
Затем мы печатаем этот ключ.
Perl на помощь:
perl -lne 'BEGIN { $count = @ARGV }
$h{$_}{$ARGV} = 1;
}{
print $_ for grep $count == keys %{ $h{$_} }, keys %h
' file* > newfile
-n
читает входные файлы построчно-l
добавляет новую строку вprint
@ARGV
массив содержит имена входных файлов, присваивая его$count
наBEGIN
Нин просто считает их$ARGV
содержит имя текущего входного файла$_
содержит текущую строку, прочитанную из файла.%h
хеш содержит идентификаторы в качестве ключей, каждый ключ содержит ссылку на хеш с именами файлов, которые содержат идентификатор в качестве ключей}{
является оператором "эскимосского приветствия", он вводит код, который выполняется после исчерпания ввода- мы выводим только идентификаторы, количество файлов которых эквивалентно количеству всех файлов. Это работает для любого количества файлов.
grep -hxf file1 file2 file3 file4 |sort -u
id2
id3
# For storing it to any file,
grep -hxf file1 file2 file3 file4 |sort -u > output.txt
Команда zet обеспечивает набор операций между входными файлами. Использовать
intersect
возможность получить общие строки во всех входных файлах. Входной контент не нужно сортировать. Порядок вывода будет таким же, как порядок входных строк.
$ zet intersect file1 file2 file3 file4
id2
id3
Вот некоторые важные детали из раздела примечаний:
- Каждая строка вывода встречается только один раз, потому что мы рассматриваем файлы как наборы, а строки как их элементы.
- Zet считывает файлы целиком в память. Его использование памяти примерно пропорционально размеру файла его самого большого аргумента плюс размер (возможного) вывода.