Сравните строки в двух файлах

Я пытаюсь получить имя пользователя из одного файла и соответствующие ему данные из моего другого файла. Я использую 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
0
задан 21 August 2014 в 18:38

5 ответов

Можно использовать файл имени пользователя команды

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)
0
ответ дан 21 August 2014 в 18:38

В сценарии 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
4
ответ дан 21 August 2014 в 18:38

С заменой процесса в 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')

3
ответ дан 21 August 2014 в 18:38

Вот 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. Другими словами, это будет только выполнено, когда второй файл будет считан.
2
ответ дан 21 August 2014 в 18:38

Попробуйте моим кодом:

Первый вид и 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
0
ответ дан 21 August 2014 в 18:38

Другие вопросы по тегам:

Похожие вопросы: