Следующая последовательность команд powershell делает свое дело:
$repeats = [Linq.Enumerable]::Count([System.IO.File]::ReadLines("<path to current dir>\\data.txt")) - 1; copy-item -path data.txt -destination work.txt; for ($i=1; $i -le $repeats; $i++) { (Get-Content -Raw work.txt) -replace '(?s)(\d{3}\.\d{3}\.\d{4};)(([^\r\n]+[\r\n]+)*)\1', '$1$2' | Out-File result.txt; move-item -path result.txt -destination work.txt -force }; move-item -path work.txt -destination result.txt -force
Объяснение
Scripting
Для обсуждения командная строка разбита на одну команду на строку. Предполагается, что исходные данные находятся в 'data.txt and a temp file
work.txt can be used.
result.txt` будет содержать результат.
Основная идея:
- Разработайте регулярное выражение, используя обратные ссылки для выражения повторного совпадения.
- Повторно выполнить это регулярное выражение.
Каждый прогон удаляет 1 дубликат для каждого значения в первом столбце.
- Консервативно оцените максимальное количество повторений заранее.
Решение далеко не элегантное и эффективное (некоторые идеи см. В разделе обзора).
Оцените количество прогонов.
Как мы увидим, каждый прогон удаляет 1 дубликат для каждого значения в первом столбце. Таким образом, в худшем случае (т.е. каждая строка начинается с одного и того же префикса) это означает, что no. of lines - 1
выполняется. Определите это число, сохраните его в переменной $repeats
.
Кредиты : Эта строка была взята из другого ответа SO .
$repeats = [Linq.Enumerable]::Count([System.IO.File]::ReadLines("<path to current dir>\\data.txt")) - 1;
Делопроизводство: скопировать оригинал в рабочий файл
copy-item -path data.txt -destination work.txt;
Повторите замену $repeats
раз
for ($i=1; $i -le $repeats; $i++) {
Замена на основе регулярных выражений.
- Сопоставьте префикс строки + остаток строки + любое количество строк без префикса + повторяющийся префикс, встречающийся снова.
- Делопроизводство: переименуйте файл результатов в рабочий файл
Credits : Команда применить регулярное выражение к текстовому файлу, взятому из этого SO ответа
(Get-Content -Raw work.txt) -replace '(?s)(\d{3}\.\d{3}\.\d{4};)(([^\r\n]+[\r\n]+)*)\1', '$1$2' | Out-File result.txt;
move-item -path result.txt -destination work.txt -force
};
Делопроизводство: переместить последний экземпляр рабочего файла в файл результатов
move-item -path work.txt -destination result.txt -force
Regex
Диалект регулярного выражения для powershell - это .NET.
Задача заключается в удалении каждой копии префикса при сохранении промежуточного материала. Однократное выполнение регулярного выражения не будет успешным, поскольку последовательные совпадения будут перекрываться.
Пошаговое обсуждение:
а. Выберите соответствие одной линии.
Необходимо, так как совпадения будут пересекать границы линий
(?s)
б. Шаблон соответствия префикса
Очевидно, этот подшаблон необходимо изменить в соответствии с фактическим форматом префикса. Эта форма (3-3-4 десятичных знака vlock, разделенных .
) получена из примера.
Обратите внимание на завершающий ;
и скобки, чтобы определить группу захвата для совпадений этого подшаблона. На эту группу / матч захвата ссылаются позже
(\d{3}\.\d{3}\.\d{4};)
с. Промежуточный текст
Остаток строки, в которой совпадает подвыражение b.
+ последовательность разделителей строк + произвольное количество строк.
Due to the greedy greedy ( 'match as much as you can' ) nature of repetition operators ( `*` ), this part would match the remainder of the file (assuming it ends with a line separator).
(([^\r\n]+[\r\n]+)*)
д. Префикс клона
Префикс, соответствующий подвыражению из b.
, должен произойти снова, чтобы произошла замена. Фактически это соответствует последнему клону префикса, сопоставленному с b.
\1
Как и задумано, регулярное выражение обнаруживает клонов только в начале строки
Обзор
Хотя было бы возможно сопоставить весь набор префиксных клонов и их промежуточных строк по шаблону, аналогичному приведенному, - в основном выбирая не жадное сопоставление («сопоставляйте как можно меньше») - я не знать любой способ отбросить точно клоны префикса при указании замены.
Количество повторений может быть уменьшено путем сопоставления только последовательных строк с одинаковым префиксом, исключая второе вхождение в каждом совпадении. Таким образом, было бы несколько совпадений / замен за проход. В основном это уменьшает число итераций log ( no. of lines )
. Он обязывает измененное регулярное выражение обслуживать 1 промежуточную строку между 2 последовательными вхождениями префикса. Это изменение должно относиться только к очень большим файлам
Табличная форма исходного файла предполагает, что данные поступают из базы данных или электронной таблицы.Эти рабочие среды были бы намного лучше подходящими для выполнения поставленной задачи, поэтому, если есть какая-либо возможность изменить данные перед тем, как они будут выгружены в виде файла, это должно быть предпочтительным способом.
Более подходящие инструменты, позволяющиедля некоторого вида анализа столбца и дедупликации в первом столбце могут быть доступны в виде соответствующих команд powershell или инструментов командной строки.