Порівняйте два файли з першим стовпцем та видаліть повторюваний рядок із другого файлу в скрипті оболонки


9

Я поставлю своє питання на прикладі. У мене є 2 файли:

Файл №1:

118D FC300_R5_TP  FX.B      32775       2112   6       2038   6       2112   0
118E FC300_R5_TP  FX.B      32775       2136   7       2065   6       2136   0
118F FC300_R5_TP  FX.B      32775       2124   6       2064   6       2124   0
1190 FC300_R5_TP  FX.B     819210     814632  99     814609  99     814632   0
1191 FC300_R5_TP  FX.B     819210     104100  13     103714  13     104100   0
1192 FC300_R5_TP  FX.B    1638420    1609476  98    1609402  98    1609476   0
1196 FC300_R5_TP  FX.B    1638420    1638432 100    1638379 100    1638432   0
119A FC300_R5_TP  FX.B    3276840    3271776 100    3271698 100    3271776   0
119E FC300_R5_TP  FX.B    3276840    3264120 100    3264034 100    3264120   0
11A2 FC300_R5_TP  FX.B    3276840    2328648  71    2328546  71    2328648   0
11A6 FC300_R5_TP  FX.B    3276840    2328444  71    2328355  71    2328444   0
11AA FC300_R5_TP  FX.B    3276840    2328528  71    2328403  71    2328528   0
11AE FC300_R5_TP  FX.B    3276840    2328648  71    2328468  71    2328648   0
11B2 FC300_R5_TP  FX.B    3276840    2130000  65    2129766  65    2130000   0
173A FC300_R5_TP  FX.B    6553680    6478572  99    6477747  99    6478572   0

Файл №2:

11AA FC300_R5_TP  FX.B    3276840    2328528  71    2328403  71    2328528   0
11AE FC300_R5_TP  FX.B    3276840    2328648  71    2328468  71    2328648   0
11B2 FC300_R5_TP  FX.B    3276840    2130000  65    2129766  65    2130000   0
173A FC300_R5_TP  FX.B    6553680    6478572  99    6477747  99    6478572   0
0BDB FC600_R5_TP  FX.B   33554640    6044364  18    6033105  18    6044364   0
0BDC FC600_R5_TP  FX.B   33554640    6613536  20    6481974  19    6613536   0
0BDD FC600_R5_TP  FX.B   33554640    4435848  13    4057170  12    4435848   0
0BDE FC600_R5_TP  FX.B   33554640    6620868  20    6249518  19    6620868   0

Бажаний вихід

Файл №3:

0BDB FC600_R5_TP  FX.B   33554640    6044364  18    6033105  18    6044364   0
0BDC FC600_R5_TP  FX.B   33554640    6613536  20    6481974  19    6613536   0
0BDD FC600_R5_TP  FX.B   33554640    4435848  13    4057170  12    4435848   0
0BDE FC600_R5_TP  FX.B   33554640    6620868  20    6249518  19    6620868   0

Я хотів би порівняти файл 1 і файл 2 за допомогою своїх перших стовпців і видалити весь рядок або рядок з файлу 2 там, де вони відповідають файлу 1. Я також хотів би зберегти результати в 3-му файлі, файл №3.

Відповіді:


10

Ви можете використовувати awkдля цього:

awk 'FNR==NR{a[$1];next};!($1 in a)' file1 file2 > file3

Пояснення:

  • FNR == NR: Цей тест справедливий, коли кількість записів дорівнює кількості записів у файлі. Це справедливо лише для першого файлу, для другого файл NRбуде дорівнює кількості рядків file1 + FNR.

  • a[$1]: Створіть індекс елементів масиву першого поля file1.

  • next: перехід до наступного запису, тому більше файлу не буде оброблено.

  • !($1 in a): Перевірте, чи є перше поле ($ 1) в масиві, тобто у file1, і надрукуйте весь рядок (у файл3).

На основі одного з прикладів з вікі #awk .


Ідеальний відповідь !!!
mtk

8
export LC_ALL=C
comm -13 <(sort f1) <(sort  f2)

Повідомлять про рядки, які є лише у f2.

export LC_ALL=C
join -v2 <(sort f1) <(sort f2)

Буде повідомлено рядки f2, перше поле яких не знайдено як перше поле в жодному рядку f1.

(Вам потрібна оболонка з підтримкою підстановки процесів , як ksh93, zshабо bash).


2

Просто для задоволення ось рішення в Perl:

#!/usr/bin/perl

# create names lookup table from first file
my %names;
while (<>) {
    (my $col1)= split / /, $_;
    $names{$col1} = 1;
    last if eof;
}

# scan second file
while (<>) {
    print if /^(\S+).*/ && not $names{$1};
}

Приклад

$ ./showdiffs.pl file1  file2
0BDB FC600_R5_TP  FX.B   33554640    6044364  18    6033105  18    6044364   0
0BDC FC600_R5_TP  FX.B   33554640    6613536  20    6481974  19    6613536   0
0BDD FC600_R5_TP  FX.B   33554640    4435848  13    4057170  12    4435848   0
0BDE FC600_R5_TP  FX.B   33554640    6620868  20    6249518  19    6620868   0

Деталі

Розчин Perl, наведений вище, складається з 2-х петель. Перший цикл читає всі рядки з file1і створює хеш, %namesкуди додається кожен стовпець, який ми ідентифікуємо.

$names{11AA} = 1;

Потім другий whileцикл працює над другим файлом, file2і стовпець 1 кожного рядка ідентифікується за допомогою регулярного виразу:

^(\S+).*

Вище сказано з початку рядка, зіставте все, що не є пробілом, і збережіть його у тимчасовій змінній $1. Це врятується, обернувши навколо нього паролі. .*Каже , що потрібно все інше на лінії.

Наступний біт , що лінії говорить дивитися вгору трохи стовпець 1 , який ми тільки що збережений в $1в %namesхеш:

$names{$1}

Якщо він присутній там, ми не хочемо його друкувати. Якщо його там немає, то роздрукуйте його.


2

Спосіб 1 # Баш

#!/usr/bin/env bash
file1=$1
file2=$2

[[ $# -ne 2 ]]  && { echo -e "\n\tUsage: \t$0 file1 file2\n"; exit 1; }

while read line
do

        if ! grep -q "${line%% .*}" $file1; then
                echo "${line}"
        fi

done < $file2

Спосіб 2 # Тільки Греп

grep -v "$(< file1)" file2

grep працює, але не є гарантією


1

Давайте отримаємо це як

Файл №1: file1.txt

Файл №2: file2.txt

Потім запустіть наступне на терміналі

fgrep -vf test1.txt test2.txt > output.txt

output.txt буде містити бажані результати.

Пояснення:

fgrep : print lines matching a pattern (from manual page)
-v  : get only non-matching rows
-f : obtain PATTERN from FILE (from manual page)

Це працює лише в тому випадку, якщо цілі рядки однакові, але запитуючий явно попросив порівняння лише в першій колонці.
Адаефон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.