Замена последних строк группы текста с помощью AWK - PullRequest
2 голосов
/ 02 октября 2011

У меня есть вывод от выполнения различных команд

d41d8cd98f00b204e9800998ecf8427e 1317522632  /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document.txt
d41d8cd98f00b204e9800998ecf8427e 1317522632 /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy.txt
d41d8cd98f00b204e9800998ecf8427e 1317522632 /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy (2).txt
d41d8cd98f00b204e9800998ecf8427e 1317506438 /home/evan/school_work/unix/Projects/Project2/finddups/.svn/tmp/tempfile.tmp

2430ffcf28e7ef6990e46ae081f1fb08 1317522636 /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2 - Copy.txt
2430ffcf28e7ef6990e46ae081f1fb08 1317506569 /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2.txt

Я хочу передать его через awk, чтобы он выглядел следующим образом

Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy (2).txt
Original: /home/evan/school_work/unix/Projects/Project2/finddups/.svn/tmp/tempfile.tmp

Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2 - Copy.txt
Original: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2.txt

Есть идеи?

Некоторые пояснения :

Последний файл перед новой строкой или EOF будет являться исходным файлом, все, что раньше должно быть помечено как дубликат.

Первый столбецmd5sum файла, секунда - дата модификации.Вы заметите, что последний файл в группе всегда будет иметь самую старую временную отметку, это критерии, которые я использую, чтобы определить, какой файл является «оригинальным», самым старым файлом.

Вот команды, которые я используюполучить список всех дубликатов

find ${PWD} -type f -exec stat -c %Y {} \; -exec md5sum '{}' \; | sed -r 'N;s/([0-9]+)\n([^ ]+) /\2 \1/g' | sort -r | uniq -w 32 --all-repeated=separate

Ответы [ 5 ]

1 голос
/ 03 октября 2011

Этот sed oneliner может работать:

sed '$G' source | # append a newline to source
sed -nr '$!{N;s/^([^ ]+ )[^ ]+ +(.*\n)\1/Duplicate: \2\1/;s/^[^ ]+ [^ ]+ +(.*\n)$/Original: \1/;P;D}'

При добавлении новой строки в исходный файл проблема становится двумя заменами, сводящими на нет все несоответствия EOF.

Я полагаю, что решение sed приемлемо, так каквы использовали sed в файле исходного кода prep.

1 голос
/ 02 октября 2011

Сортируйте строки (используя sort), сохраните хеш во временной переменной и сравните его с текущим с помощью оператора if.Другой оператор if должен избавиться от возможных пустых строк.

Например:

| sort | awk '{ if ($0) { if (TEMP != $1) { print "Original: " $0 } else { print "Duplicate:" $0 } TEMP = $1 } }'

Редактировать:

Поскольку вы предоставили эти пояснения, вы можете сделать это следующим образом:

| tac | awk '{ if ($0) { if (TEMP != $1) { print "Original: " $0 } else { print "Duplicate:" $0 } TEMP = $1 } else { print "" } }' | tac

tac инвертирует порядок строк, достигая в точности того, что было в первом примере.Второй tac восстанавливает исходный порядок.

0 голосов
/ 02 октября 2011
awk '{
  for (i = 0; ++i < NF;)
    print "Duplicate:", $i
  print "Original:", $NF    
  }' FS='\n' RS= infile
0 голосов
/ 02 октября 2011

Возможно, это сработает, если после последней строки каждой группы, включая самую последнюю группу, появятся пустые строки и если имена файлов никогда не будут содержать пробелов. Это зависит от наличия пустых строк.

awk 'NF == 3 { if (save != "") { printf("Duplicate: %s\n", save); } save = $3; }
     NF == 0 { printf("Original:  %s\n", save); save = ""; }'

Если последняя пустая строка отсутствует, последняя строка не будет напечатана.

Это не работает из-за пробелов в именах файлов (поэтому большинство строк не имеют только 3 поля). Awk на самом деле не самый подходящий инструмент. Я склонен использовать Perl, когда Awk не подходит:

#!/usr/bin/env perl
use strict;
use warnings;
my $save = "";

while (<>)
{
    chomp;
    if ($_ =~ m/^ (?:[\da-fA-F]+) \s+ (?:\d+) \s+ (\S.*)/x)
    {
        print "Duplicate: $save\n" if $save ne "";
        $save = $1;
    }
    else
    {
        print "Original:  $save\n\n";
        $save = "";
    }
}

Это производит:

Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy (2).txt
Original:  /home/evan/school_work/unix/Projects/Project2/finddups/.svn/tmp/tempfile.tmp

Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2 - Copy.txt
Original:  /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2.txt

Если вам нужно использовать Awk, вам нужно будет работать с $0 при NF >= 3, удаляя хеш и номер inode (или любое другое значение в строке данных), чтобы найти имя файла.

0 голосов
/ 02 октября 2011

Откуда вы знаете, что такое дубликат и что такое копия?Это был бы мой вопрос.

Было бы легко, если бы у всех дубликатов было Copy в имени, но ваш первый пример, один из первых дубликатов называется New Text Document.txt, а оригинал находится в.svn каталог, который никогда не нужно было просматривать.

Похоже, у вас есть хэш MD5 в первом столбце, что означает, что вы можете отсортировать по нему, а затем использовать awk для циклического просмотра выходных данных ипечатать пустую строку всякий раз, когда изменяется хэш.Это сгруппировало бы ваши файлы.

Оригинал против копии будет намного сложнее.Вам придется выработать хорошие критерии для этого.Вы можете выбрать самую раннюю дату изменения (mdate).Вы могли бы сортировать по этому тоже.Когда вы разбиваете хеш, вы можете просто предположить, что первый файл в списке (потому что он имеет самую раннюю дату) является оригиналом.

Или вы можете просто предположить, что файлы со словом Copy в названии файла находятся копии.И тогда, это может не иметь большого значения.Вы хотите, чтобы программа просто идентифицировала дубликаты или удалила их?Если программа просто идентифицирует дубликаты, нет необходимости выяснять, какие из них являются оригиналами, а какие - дубликатами.Вероятно, вы можете сделать это лучше, чем любой алгоритм.

Кстати, какие именно три столбца.Я предполагаю, что первым является has, а последним - имя файла, но какое среднее?

...