2016-11-24 2 views
1

У меня есть база данных в этом формате:Finding диапазон номеров с Grep

username:something:UID:something:name:home_folder

Теперь я хочу, чтобы увидеть, какие пользователи имеют UID в диапазоне от 1000-5000. Это то, что я пытался сделать:

ypcat passwd | grep '^.*:.*:[1-5][0-9]\{2\}:'

Мое мышление заключается в следующем: я иду в третьей колонке и найти номера, которые начинаются с числа 1-5, то следующий номер может быть любое количество - диапазон [0-9], и этот диапазон повторяет себя еще 2 раза, делая его 4-значным числом. Другими словами, это было бы что-то вроде .

Мой вывод, однако, содержит даже UID, которые больше 5000. Что я делаю неправильно?

Кроме того, я понимаю, что код, который я написал, потенциально может содержать номера до 5999. Как я могу сделать число 1000-5000?

EDIT: Я намеренно не использую awk, так как хочу понять, что я делаю неправильно с grep.

+1

'. *' жадный .. проверьте, совпадают ли цифры в других полях – Sundeep

+0

Я должен смотреть только на третье поле, так как мой диапазон граничит с обеих сторон: ' –

+0

не обязательно как есть и другие ':' в строке – Sundeep

ответ

3

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

  • Как Sundeep отметил в комментариях, ^.*:.*: будут соответствовать два или более колонн, так как .* части может соответствовать полям разделителей («:»), как а также содержимое поля. Чтобы исправить это, используйте ^[^:]*:[^:]*: (или, что то же самое, ^\([^:]:\)\{2\}); см ноты на брекет выражений и основные против расширенного синтаксиса RE ниже)
  • [0-9]\{2\} будет точно соответствовать две цифры, а не три
  • Как вы поняли, это соответствует номера, начинающиеся с «5», а затем, кроме «0»
  • цифр

в результате этих проблем, шаблон ^.*:.*:[1-5][0-9]\{2\}: будет соответствовать любой записи с UID или GID в диапазоне 100-599.

Чтобы сделать это правильно с помощью grep, используйте grep -E '^([^:]*:){2}([1-4][0-9]{3}|5000):' (снова см. Комментарии Sundeep).

[Добавлено в редактировании:] Относительно скобка выражения и какие ^ средство в них, вот соответствующий раздел re_format man page:

выражение в квадратных скобках представляет собой список символов, заключенных в «[]». Он обычно соответствует любому одиночному символу из списка (но см. Ниже). Если список начинается с '^', он соответствует любому одиночному символу (но см. Ниже ), а не остальную часть списка. Если два символа в списке разделены знаком «-», это сокращает весь диапазон символов между этими двумя (включительно) в последовательности сортировки, , например. '[0-9]' в ASCII соответствует любой десятичной цифре.

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

Относительно базового и расширенного синтаксиса RE: grep -E использует «расширенный» синтаксис, который достаточно разный, чтобы помешать вам. Соответствующие отличия здесь заключаются в том, что в базовом RE символы «() {}» рассматриваются как буквенные символы, если не экранированы (если они экранированы, они рассматриваются как синтаксис RE, указывающий на группировку и повторение); в расширенном RE это обратное: они рассматриваются как синтаксис RE, если они не экранированы (если они экранированы, их обрабатывают как буквенные символы).

Вот почему я предлагаю ^\([^:]:\)\{2\} в первой точке, но тогда на самом деле используйте ^([^:]*:){2} в предлагаемом решении - первый - это базовый синтаксис, второй - расширенный.

Другая соответствующая разница - и поэтому я перешел на продленный на фактическое решение - это то, что только расширенный RE позволяет | указать альтернативы, как в this|that|theother (который соответствует «это» или «что» или «theother «). Мне нужна эта возможность для соответствия четырехзначному номеру, начиная с 1-4 или определенного количества 5000 ([1-4][0-9]{3}|5000). Просто нет возможности сделать это в базовом RE, так что grep -E и расширенный синтаксис требуются здесь.

(Есть также много других вариантов RE, таких как RERE-совместимый RE (PCRE). При использовании регулярных выражений всегда обязательно узнайте, какой вариант использует ваш инструмент regex, поэтому вы не используете синтаксис, t понимают.)

+2

, вероятно, добавьте 'grep -E '^ ([^:] *:) {2} ([1-4] [0-9] {3} | 5000):' 'также версия .. легко изменить столбец совпадают с этим .. – Sundeep

+0

У меня проблемы с пониманием '[^:]' - так, как меня учили, квадратные скобки указывают диапазон, а пробелы обозначают 'test'. '^' указывает начало строки. Что это значит? –

+1

'[^:] *: [^:] *:' -> '([^:] *:) {2}' для более общего/расширяемого решения. Квадратные скобки не указывают диапазон, они указывают выражение скобки, в котором может быть список символов '[abc]' или диапазон символов '[ac]' или класс символов '[[: alpha:]]' и ведущий '^' означает «нет». –

2
ypcat passwd |awk -F: '$3>1000 && $3 <5000{print $1}' 

awk Здесь можно легко выполнить задачу. Здесь мы сделали «:» как разделитель между полями и установили условие, что третье поле должно быть больше 1000 и меньше 5000. Если это условие соответствует первому полю печати.

+1

Ха-ха, точно такой же ответ. Я думаю, вы избили меня примерно на 10 секунд. – VM17

+0

Спасибо, но я все еще хочу знать, что не так с моим кодом. –

+1

Главное, что неправильно с вашим кодом, вы пытаетесь использовать регулярное выражение, когда арифметическая операция, как в этом решении, является, безусловно, правильным подходом. 'Некоторые люди, столкнувшись с проблемой, думают « Я знаю, я буду использовать регулярные выражения ». Теперь у них две проблемы.» - источник оспаривается. –

Смежные вопросы