Один из подходов заключается в том, чтобы сначала найти все наборы из 12 начальных символов, которые присутствуют более чем в одном файле:
cut -c-12 file* | sort | uniq -c
Команда cut
выше печатает первые 12 символов из каждого файла, имя которого начинается с file
, затем они сортируются, и количество раз, которое встречается в каждой строке, добавляется командой uniq -c
. Выполнение этой процедуры на файлах вашего примера дает результат:
$ cut -c-12 file* | sort | uniq -c
1 -13 -3 -1
2 -13 -3 -2
2 -13 -3 -3
2 -13 -4 0
2 -13 -4 -1
2 -13 -4 -2
2 -13 -5 0
Итак, все строки, кроме первой, появляются в обоих файлах. Теперь сохраните только те строки, которые появляются нужное количество раз (20 в вашем случае):
cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev
rev
просто печатает свои входные данные в обратном порядке. Я использую его здесь для того, чтобы сделать последним полем количество просмотров каждой строки. Затем это поле передается в sed
, который получает команду печатать только строки, заканчивающиеся пробелом, цифрой 20 и 0 или более пробелов. В результате остаются только строки, которые появились 20 раз, а заключительный rev
возвращает нас к исходному формату.
Теперь вы можете передать все это в grep
как список строк для поиска:
$ grep -f <(cut -c-12 file* | sort | uniq -c |
rev | sed -n 's/ 20 *$//p' | rev) file*
-13 -5 0 19.3769 46.9197 1
-13 -4 -2 347.911 57.7232 1
-13 -4 -1 38.5696 39.0027 1
-13 -4 0 2227.39 124.894 1
-13 -3 -3 113.001 40.2117 1
-13 -3 -2 850.847 78.2881 1
Если ваш shell не поддерживает формат <()
, вы можете сохранить результаты cut
в отдельный файл и использовать его, или просто запустить его в цикле:
cut -c-12 file* | sort | uniq -d |
while IFS= read -r l; do grep -- "^$l" file1; done
Для вывода каждого файла в отдельный файл используйте:
cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev > list
for f in file*; do grep -f list "$f" > "$f.new"; done