У меня есть два файла:
#a.txt
11
22
33
44
55
11
И
# b.txt
55
66
77
88
99
11
Я делаю эту команду для печати дублирующихся строк через два файла: sort *.txt | uniq -D
И это производит:
11
11
11
55
55
Я хотел бы, чтобы это произвело точные местоположения; т.е. для строки 1 от вывода это должно сказать, куда это прибыло из: строка 1, файл a.txt т.е. своего рода различное.
Какие-либо идеи, как я могу сделать это?
можно сделать что-то вроде этого:
file_expr="*.txt"; sort $file_expr | sed 's/^\s*//; s/\s*$//; /^\s*$/d' | uniq -d | while read dup_line; do grep -Hn "^\s*$dup_line\s*$" $file_expr; done| sort -t: -k3 -k1,2 | awk -F: '{ file=$1; line=$2; $1=$2=""; gsub(/(^[ \t]+)|([ \t]+$)/,"",[110]); if (prev != "" && prev != [110]) printf ("\n"); printf ("\033[0;33m%s (line %s)\033[0m: %s\n", file, line, [110]); prev=[110]; }'
Результат:
a.txt (line 3): 11
a.txt (line 8): 11
b.txt (line 8): 11
a.txt (line 7): 55
b.txt (line 3): 55
Изменение содержание переменной file_expr
для изменения файлов влияло
, я использовал эти sed
команда к [1 136] обрезка весь запаздывание и продвижение , пробелы и удаляют пустые строки , делание эти uniq -d
получает только строки, которые являются ДЕЙСТВИТЕЛЬНО дубликатом...
Затем я цикл по дублирующимся строкам (распечатал один для каждого соответствия), и я grep
их в файлы с помощью флагов -n
( строка файла и печати ) и -H
( всегда показывают имя файла ). Выражение ^\s*$dup_line\s*$
в эти grep
заставляет его соответствовать целая строка (так, чтобы, например, "стандартное расположение букв на клавиатуре 11 uiop" не соответствовал).
, Как Вы видите, это работает оба использования файл globbing ...
file_expr="*.txt"; sort $file_expr | sed 's/^\s*//; s/\s*$//; /^\s*$/d' | uniq -d | while read dup_line; do grep -Hn "^\s*$dup_line\s*$" $file_expr; done
Результат:
a.txt:3:11
a.txt:8:11
b.txt:8:11
a.txt:7:55
b.txt:3:55
... и литеральные имена файлов ..
file_expr="a.txt b.txt"; sort $file_expr | sed 's/^\s*//; s/\s*$//; /^\s*$/d' | uniq -d | while read dup_line; do grep -Hn "^\s*$dup_line\s*$" $file_expr; done
Результат:
a.txt:3:11
a.txt:8:11
b.txt:8:11
a.txt:7:55
b.txt:3:55
<час> я затем играл вокруг немного для создания его визуально больше удобный ... Как это:
file_expr="a.txt b.txt"; sort $file_expr | sed 's/^\s*//; s/\s*$//; /^\s*$/d' | uniq -d | while read dup_line; do grep -Hn "^\s*$dup_line\s*$" $file_expr; done| sort -t: -k3 -k1,2 | awk -F: '{ file=$1; line=$2; $1=$2=""; gsub(/(^[ \t]+)|([ \t]+$)/,"",[116]); if (prev != "" && prev != [116]) printf ("\n"); printf ("\033[0;33m%s (line %s)\033[0m: %s\n", file, line, [116]); prev=[116]; }'
Результат:
a.txt (line 3): 11
a.txt (line 8): 11
b.txt (line 8): 11
a.txt (line 7): 55
b.txt (line 3): 55
В этом последнем представлении все является более "человеческим", и дубликаты группируются сначала результатом и затем файлом (Вы видите, что результаты в [1 116] являются всеми вместе), таким образом, легче понять..
имя файла и строка теперь желтые (\033[0;33m
) для различения от текста в фактической строке в случае мультилинии (извините игру слов слова), дубликаты
С тех пор в Вашем примере b.txt
файл имеет пробелы в нем, можно использовать awk
для захвата символов перед пространством.
Преобразование из моих комментариев выше к ответу здесь. Можно использовать grep -n
для показа номера строки и файла, из которого он прибыл. Также добавьте в еще одном uniq
команда так, чтобы, когда grep циклы через дубликаты нашли, она не проходила 3 11 и 2 55.
Быстрый пример:
sort *.txt | awk '{print $1}' | uniq -D
11
11
11
55
55
Путем добавления во втором uniq
вывод только:
11
55
Теперь мы можем добавить в grep
и while
цикл. grep
покажет нам, сколько раз каждый появляется и в каком файле они находятся.
sort *.txt | awk '{print $1}' | uniq -D | uniq | while read num; do grep -n $num *.txt; done
Пример:
$ sort *.txt | awk '{print $1}' | uniq -D | uniq | while read num; do grep -n $num *.txt; done
a.txt:2:11
a.txt:7:11
b.txt:7:11
a.txt:6:55
b.txt:2:55