У меня есть 3 текстовых файла (A, B и C), в каждом по несколько сотен адресов электронной почты. Я хочу объединить список A и список B в один файл, игнорируя различия в регистре и пробеле. Затем я хочу удалить все электронные письма в новом списке, которые находятся в списке C, снова игнорируя различия в регистре и пробеле.
Я предпочитаю язык программирования C++, но, похоже, он плохо подходит для этой задачи. Есть ли язык сценариев, который мог бы делать это (и подобные задачи) в относительно небольшом количестве строк?
Или уже существует программное обеспечение (бесплатное или коммерческое), которое позволило бы мне это сделать? А можно, например, в Excel?


Самый быстрый способ сделать это, вероятно, не обязательно потребует кодирования. Вы можете импортировать файлы A и B в Excel на одном листе, а затем (при необходимости) выполнить фильтр по полученному списку адресов, чтобы удалить любые дубликаты.
Следующим шагом будет импорт файла C на второй лист. На третьем листе вы должны выполнить ВПР, чтобы выбрать все адреса из вашего первого списка и удалить их, если они находятся в вашем «Списке C».
ВПР будет выглядеть примерно так:
= ЕСЛИ (ISNA (ВПР (email_address_cell, Sheet2! email_duplicates_list, 1, false), "", (VLOOKUP (email_address_cell, Sheet2! email_duplicates_list, 1, false)))
Я также включил проверку, чтобы увидеть, возвращает ли формула ошибку «Значение недоступно», и в этом случае в ячейке отображается просто пустое значение. Оттуда вам просто нужно удалить пустое пространство, и вот ваш окончательный список.
Теперь, сказав все это, вы все равно можете сделать макрос VBA, чтобы сделать то же самое, но, возможно, немного очистить списки, в зависимости от того, что вам нужно. Надеюсь, это поможет!
Какое требование? Мы хотим игнорировать различия в регистре (что Excel будет делать по умолчанию) и пробелы. По общему признанию, вы получите несколько пустых строк, используя приведенное выше предложение, но их можно легко удалить с помощью другого автофильтра.
Для обработки текста того типа, который вы описываете, идеально подходят perl или python.
Вы можете использовать ассоциативные массивы (в данном случае массивы со строковым индексом) для хранения адресов электронной почты в списке.
Используйте адрес электронной почты в нижнем регистре без пробелов в качестве ключа и реальный адрес электронной почты в качестве значения.
Затем нужно прочитать и сохранить первый файл, прочитать и сохранить второй (который перезапишет адреса электронной почты с тем же ключом), затем прочитать третий файл и удалить записи из списка с этим ключом.
То, что у вас остается, - это список, который вы хотите (A + B - C).
Псевдокод здесь:
set list to empty
foreach line in file one:
key = unwhitespace(tolowercase(line))
list{key} = line
foreach line in file two:
key = unwhitespace(tolowercase(line))
list{key} = line
foreach line in file three:
key = unwhitespace(tolowercase(line))
if exists(list{key})
delete list{key}
foreach key in list:
print list{key}
Excel может это сделать, как указано выше. Однако наиболее подходящим языком программирования является Perl.
В Python примерно так:
Обратите внимание, что это приведет к записи электронных писем в нижнем регистре в окончательный результат. Если это не так, тогда потребуется решение на основе словаря.
def read_file(filename):
with file(filename, "r") as f:
while True:
line = f.readline();
if not line:
break;
line = line.rstrip();
if line:
yield line;
def write_file(filename, lines):
with file(filename, "w") as f:
for line in lines:
f.write(line + "\n");
set_a = set((line.lower() for line in read_file("file_a.txt")));
set_b = set((line.lower() for line in read_file("file_b.txt")));
set_c = set((line.lower() for line in read_file("file_c.txt")));
# Calculate (a + b) - c
write_file("result.txt", set_a.union(set_b).difference(set_c));
Как упоминалось в Excel, вы также можете делать такие вещи с помощью Jet и VBScript.
Set cn = CreateObject("ADODB.Connection")
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Docs\;" _
& "Extended Properties = ""text;HDR=No;FMT=Delimited"";"
cn.Open strCon
strSQL = "SELECT F1 Into New.txt From EmailsA.txt " _
& "WHERE UCase(F1) Not IN (SELECT UCase(F1) From EmailsC.txt)"
cn.Execute strSQL
strSQL = "INSERT INTO New.txt ( F1 ) SELECT F1 FROM EmailsB.txt " _
& "WHERE UCase(F1) Not IN (SELECT UCase(F1) From EmailsC.txt)"
cn.Execute strSQL
Я думаю, что приведенные выше ответы являются ответом на технический вопрос КАК; остается только подумать, сколько раз вам придется выполнять задание. Если это разовая задача и вам удобнее работать с Excel, начните с этого. Если вы знаете, что вам придется выполнить эту задачу, по крайней мере, дважды, а может и больше, тогда лучше всего написать сценарий или исполняемый файл.
К сожалению, этот ответ, вероятно, вам не поможет, но если на самом деле вы использовали Unix (например, Linux), вы могли бы сделать что-то вроде:
cat filea >> fileb # добавить файл a в файл b
сортировать файлb | uniq> newFile # newFile теперь содержит слияние файла a и файла b с отсортированными и уникальными адресами электронной почты.
Все это можно сделать одной строкой следующим образом: кошка filea >> fileb | сортировать | uniq> newFile
Теперь вам остается просто удалить обычные электронные письма. Здесь могут быть полезны некоторые вариации "diff", например: diff newFile fileC> finalFile
diff предоставит вам список различий между двумя файлами, поэтому вывод в "finalFile" должен быть списком электронных писем, которые находятся в "newFile" (слияние A и B), но НЕ находятся в fileC. Параметры различных инструментов позволяют игнорировать пробелы и регистр. Мне пришлось бы немного поиграть с этим, чтобы понять это правильно, но изложенное выше является общей идеей.
Раньше у меня был дополнительный компьютер, работающий под Linux, с единственной целью - делать вещи, подобные вышеизложенному, что неудобно для Windoze, но совсем несложно для операционных систем типа Unix. Когда мое оборудование умерло, я так и не добрался до сборки другого Linux-компьютера.
Я считаю, что в наборе инструментов MKS для Windoze, вероятно, есть все перечисленные выше утилиты.
Как это соответствует требованиям к пробелам и регистру.