При наличии двух обычных текстовых файлов Unix цикл оболочки выводит
1235
, поскольку эта строка встречается в обоих файлах. Если это не так, то один из ваших файлов может быть текстовым файлом DOS. Вы можете преобразовать текстовые файлы DOS в текстовые файлы Unix с помощью утилиты dos2unix
.
В вашем цикле нет ничего серьезного, учитывая тип ваших данных, кроме того факта, что он вызывает grep
один раз для каждой строки в file1
. Он также будет соответствовать подстрокам, например 100
в 1001
, и будет, если какая-либо строка в file1
содержит пробелы или табуляции,разбить эти строки на несколько слов (из-за for i in $(cat...)
, где $(cat...)
не заключено в кавычки ).
Если вы хотите решить свою проблему таким способом (с циклом ), вам лучше
while IFS= read -r word; do
grep -xF -e "$word" file2
done <file1
-x
и -F
объясняются позже в моем ответе, а -e
означает, что следующим аргументом является шаблон, соответствующий (, в противном случае он может быть принят как параметр командной строки, если он запускается с тире(-
).
Это по-прежнему будет выполнять grep
один раз для каждой строки в file1
, но будет делать это правильно.
Чтобы извлечь строки в file2
, которые точно соответствуют строке в file1
, без использования цикла оболочки, вы должны использовать
$ grep -xF -f file1 file2
1235
Предполагается, что file1
содержит разумное количество строк, но не слишком много («слишком много» будет зависеть от объема имеющейся у вас памяти ).
Команда использует grep
с -x
, что приводит к совпадению только полных строк (без совпадений подстрок ), и с -F
, который изменяет grep
для сравнения строк, а не совпадений с регулярными выражениями..
-f file1
инструктирует grep
считывать шаблоны (строки для сопоставления с )из file1
.
Однако для действительно больших объемов данных было бы крайне неэффективно использовать grep
. Вместо этого для этой задачи и с этим типом данных (отдельных слов в отдельных строках )было бы лучше выполнить операцию реляционного соединения между файлами:
$ join file1 file2
1235
Это, предполагая, что оба файла лексикографически отсортированы , возвращает числа, одинаковые в обоих файлах.
Использованиеcomm
:
$ comm -1 -2 file1 file2
1235
comm
также сравнивает отсортированные файлы и может легко обрабатывать очень большие наборы данных.По умолчанию печатает три столбца:
С помощью -1
мы отключаем вывод первого столбца, а с помощью -2
отключаем второй столбец, оставляя comm
для вывода только тех строк, которые одинаковы в обоих файлах.