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

API disable|enable нестабилен и может измениться в будущем. Я предлагаю вам использовать следующую команду для удаления всех символических ссылок в /etc/rc?.d/:

update-rc.d -f tomcat remove
1
задан 21 August 2014 в 19:38

4 ответа

В сценарии python:

Прагматическое решение

В случае, если это одноразовая работа, характерная для одной ситуации, следующие работы:

[ f1]

Выход:

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

Прагматическое решение

Глядя на два файла, мы имеем дело с базами данных, причем первое поле является ключевым. Следующий сценарий более гибкий и охватывает более гибкий способ создания отчетов о двух файлах (например, в ситуациях), где у нас будет больше полей, чем здесь.

Если мы добавим extra («characterizing») ко второму файлу:

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
ответ дан 24 May 2018 в 04:27

С заменой процесса в 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 в качестве аргументов он получает два файла со отсортированным вводом.

(См. [F13])

3
ответ дан 24 May 2018 в 04:27

Вот решение 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}: напечатать первое поле этой строки, значение, сохраненное в массиве a для этого поля, а затем второе поле. Из-за next, описанного выше, это будет выполняться только тогда, когда NR не равно FNR. Другими словами, он будет запускаться только при чтении второго файла.
2
ответ дан 24 May 2018 в 04:27

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

Сначала соберите оба user-name и contacts и напишите вывод в один файл с именем user-name_contacts с помощью этого:

sort user-name contacts > user-name_contacts

Next , запустите эту команду, чтобы присоединиться к двум файлам:

sed -i '/$/N ; s/\n\(.*\):/:/' user-name_contacts

Выход:

Neeraj:149:neeraj@xyz.com Rahul:148:rahul@gmail.com Tarun:143:tarun@gmail.com
1
ответ дан 24 May 2018 в 04:27
  • 1
    Разве это не нарушит порядок? Он может не работать, если список контактов и имен пользователей не в порядке. – Prathik Rajendran M 21 August 2014 в 15:32
  • 2
    Нет, не работает. Вот результат $cat user-name A: 1 B: 2 $cat contacts B: Test2 A: Test1 $sed 's/\(.*\)://g' contacts > new-contacts $sort user-name new-contacts > user-name_contacts $sed -i '$!N;s/\n/:/g' user-name_contacts $cat user-name_contacts A: 1: B: 2 Test1: Test2 Неверный выход. – Prathik Rajendran M 21 August 2014 в 16:13
  • 3
    @PrathikRajendranM Я обновил свой ответ. – αғsнιη 21 August 2014 в 17:46

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

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