Вопрос или проблема
Я пытаюсь сравнить два файла и скопировать строку из File2.txt
на основе строки, найденной в File1.txt
.
Я хотел бы сохранить повторяющиеся строки в выводе, как это видно в File3.txt
. Было бы хорошо, если бы удалось сохранить тот же порядок. Эта команда выводит только одно вхождение.
grep -wF -f File1.txt File2.txt > File3.txt
Ниже представлен File1.txt
.
dog
dog
cat
cat
cat
mouse
snake
fish
Ниже представлен File2.txt
horse d:\horse.fbx
lion d:\lion.fbx
monkey d:\monkey.fbx
dog d:\dog.fbx
cat d:\cat.fbx
Ниже представлен File3.txt
.
dog d:\dog.fbx
cat d:\cat.fbx
Ниже представлен желаемый File3.txt
dog d:\dog.fbx
dog d:\dog.fbx
cat d:\cat.fbx
cat d:\cat.fbx
cat d:\cat.fbx
С использованием (g)awk:
gawk 'FNR==NR{ a[i++]=$0 }
FNR!=NR{ for(i in a) { if ($0~a[i]) print $0 }}' File1.txt File2.txt > File3.txt
- Первый файл читается в массив a[]
- Для второго файла тест
$0~a[i]
проверяет, совпадает ли строка с любым элементом, найденным в этом массиве
В командной оболочке bash, следующее может быть приемлемо.
while read; do grep -wF "$REPLY" File2.txt; done < File1.txt > File3.txt
Ответ или решение
Теория
Решение проблемы, описанной в вопросе, связано с уникальным подходом к обработке данных в файлах с помощью инструментов командной строки на UNIX-системах, таких как grep
и awk
. Основная задача состоит в том, чтобы сохранить порядок и количество повторяющихся строк из одного файла при их сравнении с другим файлом и записи результата в третий файл. Средства стандартной установки grep
не позволяют нативно сохранять повторяющиеся строки, что диктует необходимость использования альтернативных инструментов или методов.
Команда grep -wF -f File1.txt File2.txt > File3.txt
считывает строки из File1.txt
, ищет их в File2.txt
и записывает результат в File3.txt
. Однако, по умолчанию grep
не сохраняет дублирующиеся строки, присутствующие в File1.txt
, в результате чего они исчезают в File3.txt
.
Пример
Рассмотрим пример. Предположим, что у нас есть три файла.
File1.txt:
dog
dog
cat
cat
cat
mouse
snake
fish
File2.txt:
horse d:\horse.fbx
lion d:\lion.fbx
monkey d:\monkey.fbx
dog d:\dog.fbx
cat d:\cat.fbx
Цель состоит в том, чтобы получить File3.txt
следующим образом:
Желаемый File3.txt:
dog d:\dog.fbx
dog d:\dog.fbx
cat d:\cat.fbx
cat d:\cat.fbx
cat d:\cat.fbx
Применение
Рассмотрим два решения, которые могут помочь в достижении поставленной задачи, и оба они обеспечат желаемый результат: сохранение порядка и дублируемых строк при записи в результирующий файл.
Решение с помощью awk
:
Программирование с использованием awk
позволяет более гибко обрабатывать входные данные. Скрипт gawk
, обсуждаемый в вопросе, работает следующим образом:
gawk 'FNR==NR{ a[i++]=$0 }
FNR!=NR{ for(i in a) { if ($0~a[i]) print $0 }}' File1.txt File2.txt > File3.txt
- В первой части
FNR==NR{ a[i++]=$0 }
каждой строке изFile1.txt
приписывается индекс в массивеa[]
. - Второй блок
FNR!=NR{ for(i in a) { if ($0~a[i]) print $0 }}
проходит по элементам этого массива, сравнивая их со строками изFile2.txt
. Если соответствие найдено, строка выводится.
Этот метод позволяет сохранить все множественные вхождения строк из File1.txt
, поддерживая их исходный порядок.
Решение с помощью bash
цикла:
Другой подход предложен с использованием циклов в bash
, который не требует установки дополнительного ПО, но может быть менее производительным на больших объемах данных.
while read; do grep -wF "$REPLY" File2.txt; done < File1.txt > File3.txt
- Команда
while read
последовательно считывает строки изFile1.txt
. - Затем
grep -wF "$REPLY"
выполняет поиск каждой считанной строки вFile2.txt
. - Результаты складываются в
File3.txt
.
Это решение сохраняет мультиточные вхождения строк из File1.txt
, поддерживая желаемое поведение.
Заключение
При обработке большого объема данных и необходимости сохранения точного соответствия дублирующихся строк, выбор между awk
и bash
может быть обусловлен объемом работы и требованиями к производительности. awk
предлагает больше гибкости и возможностей для манипуляций с текстом, но требует немного больше времени на изучение. Комбинация циклов bash
является простым и элегантным решением, которое эффективно в большинстве случаев и легко интегрируется в уже существующие скрипты. Обе стратегии достойны внимания и могут быть адаптированы под конкретные нужды IT-специалиста, обладающего доступом к командной оболочке UNIX.