Поиск повторяющихся имен файлов с определенным шаблоном соответствия

Вы можете попробовать что-то вроде этого:

apt-get -s upgrade | awk '/^Inst/ {print $2}' | 
    xargs apt-cache policy | 
    awk '/:$|^$/ && ! /Version table:/ {print "\n" $0 } ; /:\/\// { print $2 }'

Вывод (только что запущенный на моей системе debian sid) выглядит так:

sqlite3:
http://my.local.mirror.redacted/debian

libsqlite3-0:
http://my.local.mirror.redacted/debian

libsqlite3-0:i386:
http://my.local.mirror.redacted/debian

python-newt:
http://my.local.mirror.redacted/debian

libnewt0.52:
http://my.local.mirror.redacted/debian

libruby:
http://my.local.mirror.redacted/debian
http://my.local.mirror.redacted/debian

mercurial:
http://my.local.mirror.redacted/debian

mercurial-common:
http://my.local.mirror.redacted/debian
http://my.local.mirror.redacted/debian

sysstat:
http://my.local.mirror.redacted/debian

libmilter1.0.1:
http://my.local.mirror.redacted/debian

Некоторые пакеты имеют два URL. Это потому, что моя система - amd64 с i386 в качестве дополнительной архитектуры, и эти пакеты имеют как amd64, так и i386 версии, доступные для обновления.

Если вы предпочитаете иметь полную строку вывода, чтобы она выглядела так:

mercurial-common:
        990 http://my.local.mirror.redacted/debian unstable/main amd64 Packages
        990 http://my.local.mirror.redacted/debian unstable/main i386 Packages

тогда просто удалите { print $2 } из второго awk скрипта.

1
03.02.2014, 08:12
2 ответа
ls *.DAT | awk -F. '{ if (c[$3$5]) print $0 ; c[$3$5]=$0}'

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

PAT1.URGRSVP.50.WR786842JOB11643.WRS20140.FILE0003.DAT
PAT1.URGRSVP.50.WR786842JOB11694.WRS20140.FILE0002.DAT

БОЛЬШЕ: Давайте рассмотрим команды awk более подробно:

if (c[$3$5]) print $0 ; c[$3$5]=$0

Вышеупомянутое состоит из двух операторов: одного оператора «if» и одно задание. Оператор «if»:

if (c[$3$5]) print $0

В этом операторе c является «ассоциативным массивом». Это означает, что вы даете ему ключ, а он возвращает вам значение. Мы используем $ 3 $ 5 в качестве ключа, где $ 3 - третий «блок» (то, что awk называет третьим «полем»), а $ 5 - пятый блокировать. Если этот ключ ранее не был назначен, то c [$ 3 $ 5] возвращает пустое (ложное) значение. Итак, если эта комбинация третьего и пятого блоков была замечена ранее, то выполняется print $ 0 , что означает, что печатается все имя файла. В противном случае оператор печати пропускается.

Второй оператор:

c[$3$5]=$0

Присваивает имя файла ( $ 0 ) ассоциативному массиву под ключом третьего и пятого полей: $ 3 $ 5 .Таким образом, в следующий раз, когда эти поля будут видны в операторе «if», оператор печати будет выполнен.

3
29.04.2021, 00:43

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

С этими именами файлов в файле с именем input это будет выглядеть так:

$ awk -F. '{if (dups[$3$5]++) print $0}' input

Если ваши имена файлов могут содержать пробелы или другие забавные символы, используйте find вместо ls для вывода списка их можно указать примерно так:

$ find . -name 'PAT1.*.DAT' -print0 | \
    awk -F. 'BEGIN{RS="\0"} {if (dups[$3$5]++) print $0}'

В качестве дополнительного преимущества вы можете проверить переменную dups в блоке END , чтобы распечатать, сколько пар каждой пары вы видели во входных данных.

1
29.04.2021, 00:43

Теги

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