Я пытаюсь получить имя пользователя из одного файла и соответствующие ему данные из моего другого файла. Я использую awk:
awk -F : '{ print $1 }' user-name
, это дает мне список всех пользователей. Так что теперь, как я могу сопоставить эти имена с другим файлом и получить вывод, например:
user-name id contact-details
Формат этих двух файлов выглядит следующим образом:
1.user-name
Tarun:143
Rahul:148
Neeraj:149
2.user-details
Tarun:tarun@gmail.com
Neeraj:neeraj@xyz.com
Rahul:rahul@gmail.com
то, что я пытаюсь получить, выглядит так:
Neeraj:149:neeraj@xyz.com
Rahul:148:rahul@gmail.com
Tarun:143:tarun@gmail.com
Можно использовать файл имени пользователя команды
join -t ":" username contacts
соединения, имеет контакты формата
user1:id1
user2:id2
, имеет формат
user1:contact1
user2:contact2
, Когда файл не отсортирован тогда, можно сделать следующий
sort -b username > username.sorted
sort -b contacts > contacts.sorted
и затем выполнить команду соединения на username.sorted и contacts.sorted
или как другой , сообщение указало, что можно сделать это непосредственно использование
join -t ":" <(sort -b username) <(sort -b contacts)
В сценарии Python:
Прагматическое решение
В случае, если это - "одно задание времени", специфичный для одной ситуации, следующих работ:
#!/usr/bin/env python3
with open(file1) as names:
names = sorted(names.readlines())
with open(file2) as data:
data = data.readlines()
for i in names:
item = i.replace("\n", "")+str([d[d.find(":"):].replace("\n", "") for d in data if d.startswith(i.split(":")[0])][0])
print(item)
Вывод:
Neeraj:149:neeraj@xyz.com
Rahul:148:rahul@gmail.com
Tarun:143:tarun@gmail.com
Или, если Вы хотите сохранить вывод непосредственно в файл:
#!/usr/bin/env python3
with open(file1) as names:
names = sorted(names.readlines())
with open(file2) as data:
data = data.readlines()
with open(file3, "wt") as output:
for i in names:
output.write(i.replace("\n", "")+str([d[d.find(":"):].replace("\n", "") for d in data if d.startswith(i.split(":")[0])][0])+"\n")
Поскольку Вы, вероятно, знаете, копируете сценарий в пустой файл, устанавливаете путь в файл 1-2 (3) (между кавычками), сохраняете его как combine.py
, выполните его командой:
python3 /path/to/combine.py
Более достойное базы данных решение
Смотря на эти два файла, мы на самом деле имеем дело с базами данных с первым полем как ключ. Следующий сценарий более гибок и касается более гибкого способа сделать сообщения об этих двух файлах в ситуациях (например), где у нас было бы больше полей, чем, здесь имеет место.
Если мы добавили бы дополнительное ("охарактеризование") поле во второй файл:
Neeraj:neeraj@xyz.com:Loves to Cook
Rahul:rahul@gmail.com:Collects empty bottles
Tarun:tarun@gmail.com:Weares his glasses upside down
Мы могли бы хотеть добавить характеристику вместо адреса электронной почты или обоих. Это попросило бы сценарий как:
#!/usr/bin/env python3
db1 = "/path/to/file1"; db2 = "/path/to/file2"
with open(db1) as data1:
rc = [l.replace("\n", "").split(":") for l in data1.readlines()]
with open(db2) as data2:
records2 = [l.replace("\n", "").split(":") for l in data2.readlines()]
uniques = sorted(set(item[0] for item in rc)) # find keys
report = []
for i in uniques:
database_1 = [r for r in rc if r[0] == i][0]
database_2 = [r for r in records2 if r[0] == i][0]
# -----------------------------------------------------------------------
# set the required fields for report here:
new_record = i, database_1[1], database_2[1]
# -----------------------------------------------------------------------
report.append((":").join(new_record))
for item in report:
print(item)
Результат
Если мы устанавливаем:
new_record = i, database_1[1], database_2[2]
Результат:
Neeraj:149:Loves to Cook
Rahul:148:Collects empty bottles
Tarun:143:Weares his glasses upside down
Но если мы устанавливаем:
new_record = i, database_1[1], database_2[1]
Результат:
Neeraj:149:neeraj@xyz.com
Rahul:148:rahul@gmail.com
Tarun:143:tarun@gmail.com
И если мы устанавливаем:
new_record = i, database_1[1], database_2[1], database_2[2]
Результат:
Neeraj:149:neeraj@xyz.com:Loves to Cook
Rahul:148:rahul@gmail.com:Collects empty bottles
Tarun:143:tarun@gmail.com:Weares his glasses upside down
С заменой процесса в bash
, мы можем сделать очень компактный вариант join
решение даже для неотсортированных входных файлов:
join -t: <(sort user-name) <(sort user-details)
Вывод точно так же, как пример произвел в вопросе:
Neeraj:149:neeraj@xyz.com
Rahul:148:rahul@gmail.com
Tarun:143:tarun@gmail.com
Мы используем первое поле/столбец обоих файлов здесь. Для использования используют другие столбцы, используют опции -1
и -2
(или -j
если это - то же поле). Чтобы быть более явными, мы могли использовать join -t: -j 1 ...
или join -t: -1 1 -2 1 ...
выше. (См. также man join
)
Части формы <(command)
заменяются именованным каналом, из которого может быть считан вывод команды. Это означает для join
управляйте, чтобы это получило два файла с отсортированным входом как аргументы.
(См. man bash | less '+/Process Substitution'
)
Вот awk
решение:
$ awk -F: -v OFS=: 'NR==FNR{a[$1]=$2; next}{print $1,a[$1],$2}' user-name user-details
Tarun:143:tarun@gmail.com
Neeraj:149:neeraj@xyz.com
Rahul:148:rahul@gmail.com
-F:
: устанавливает разделителя полей на :
. -v OFS=:
: устанавливает выходного разделителя полей (OFS
) к :
для симпатичной печати. NR==FNR
: NR
текущий номер строки и FNR
номер строки текущего файла. При парсинге больше чем 2 файлов, NR
будет равно FNR
только для 1-го файла. NR
увеличен для каждой строки входа в то время как FNR
сбрасывается каждый раз, когда новый файл читается. {a[$1]=$2; next}
: это создает названный ассоциативный массив a
чей ключ является первым полем и чье значение является вторым. После того как это сделано, мы пропускаем к следующей строке с next
.{print $1,a[$1],$2}
: распечатайте 1-е поле этой строки, значение, сохраненное в a
массив для того поля и затем второго поля. Из-за next
объясненный выше, это будет только выполняться когда NR
не равно FNR
. Другими словами, это будет только выполнено, когда второй файл будет считан. Попробуйте моим кодом:
Первый вид и user-name
и contacts
и запись вывод в один файл, названный user-name_contacts
с этим:
sort user-name contacts > user-name_contacts
Затем, выполняет эту команду для присоединения к двум файлам:
sed -i '/$/N ; s/\n\(.*\):/:/' user-name_contacts
Вывод:
Neeraj:149:neeraj@xyz.com Rahul:148:rahul@gmail.com Tarun:143:tarun@gmail.com