Невозможно найти имена, которые содержат три 7 в случайном порядке по AWK / Python / Bash - PullRequest
0 голосов
/ 12 марта 2009

Мне нужно найти имена, которые содержат три числа 7. В случайном порядке.

Моя попытка

Нам нужно найти имена, которые не содержат семь

ls | grep [^7]

Тогда мы могли бы удалить эти совпадения из всего пространства

ls [remove] ls | grep [^7]

Проблема в моем псевдокоде начинает быстро повторяться.

Как вы можете найти имена, которые содержат три 7 в случайном порядке по AWK / Python / Bash?

[править] Имя может содержать любое количество букв и содержит слова из трех 7.

Ответы [ 5 ]

7 голосов
/ 12 марта 2009

Я не понимаю часть о "случайном порядке". Как вы различаете «порядок», когда повторяется один и тот же токен? «A7b7» отличается от «c7d7» в порядке 7с?

В любом случае, это должно сработать:

 ls *7*7*7*

Это просто позволило оболочке решить проблему, но, возможно, я не понял правильно.

РЕДАКТИРОВАТЬ: вышеупомянутое неверно, оно включает случаи с более чем четырьмя 7, которые не нужны. Предполагая, что это bash, и расширенная глобализация включена, это работает:

ls *([^7])7*([^7])7*([^7])7*([^7])

Это читается как «ноль или более символов, которые не являются семерками, после которых следует семерка, за которыми следуют ноль или более символов, не являющихся семерками», и так далее. Важно понимать, что здесь звездочка - это оператор prefix , работающий с выражением ([^7]), которое означает «любой символ, кроме 7».

5 голосов
/ 12 марта 2009

Полагаю, вы хотите найти файлы, которые содержат ровно три семерки, но не более. Использование GNU grep с переключателем extends regexp (-E):


ls | grep -E '^([^7]*7){3}[^7]*$'

Должен сделать свое дело.

По сути, это соответствует 3 вхождениям "not 7, а затем 7", затем группе "not 7" по всей строке (^ и $ в начале и конце шаблона соответственно).

2 голосов
/ 12 марта 2009

Решение Perl:

$ ls | perl -ne 'print if (tr/7/7/ == 3)'
3777
4777
5777
6777
7077
7177
7277
7377
7477
7577
7677
...

(у меня есть каталог с 4-значными числами. 1777 и 2777 не существует.: -)

2 голосов
/ 12 марта 2009

Примерно так:

printf '%s\n' *|awk -F7 NF==4
1 голос
/ 12 марта 2009

Или вместо того, чтобы делать это в одном grep, используйте один grep для поиска файлов с 3 или более семью, а другой - для фильтрации 4 или более 7.

ls -f | egrep '7.*7.*7' | grep -v '7.*7.*7.*7'

Вы можете переместить часть работы в оболочку с помощью более короткого

ls -f *7*7*7* | grep -v '7.*7.*7.*7'

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

'-f' в 'ls' запрещает 'ls' сортировать результаты. Если в каталоге огромное количество файлов, то время сортировки может быть весьма заметным.

Этот двухступенчатый процесс фильтрации, я думаю, более понятен, чем использование шаблонов [^ 7].

Кроме того, вот решение в виде скрипта Python, поскольку вы запросили это как опцию.

import os
for filename in os.listdir("."):
    if filename.count("7") == 4:
        print filename

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...