Как проверить имя пользователя с regex?

ORDER BY в подзапросе не имеет (гарантированного) эффекта. Это должно быть для самого внешнего запроса.

Либо используйте коррелированный подзапрос в предложении ORDER BY.

SELECT ct.id,
       ct.obj_id
       FROM comment_thread ct
       ORDER BY (SELECT count(*)
                        FROM comment_comment cc
                        WHERE cc.thread_id = ct.obj_id) DESC;

Или объединение и упорядочение по левому краю по объединенному количеству.

SELECT ct.id,
       ct.obj_id
       FROM comment_thread ct
            LEFT JOIN (SELECT cc.thread_id,
                              count(*) count
                              FROM comment_comment cc
                              GROUP BY cc.thread_id) x
                      ON x.thread_id = ct.obj_id
       ORDER BY x.count DESC
                        NULLS LAST;
37
задан Cœur 10 August 2017 в 16:09
поделиться

9 ответов

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

/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/

После сопоставления одного или нескольких буквенно-цифровых символов, , если есть разделитель, за ним необходимо следовать один или несколько буквенно-цифровых символов; повторяйте по мере необходимости.

Давайте посмотрим на регулярные выражения из некоторых других ответов.

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/

По сути, это то же самое (при условии, что ваш вариант регулярного выражения поддерживает нотацию класса символов POSIX), но зачем делать разделитель необязательным? Единственная причина, по которой вы оказались в этой части регулярного выражения в первую очередь, - это наличие разделителя или другого недопустимого символа.

/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/

С другой стороны, это работает только , потому что разделитель является необязательный. После первого разделителя он может соответствовать только одному буквенно-цифровому знаку. Чтобы соответствовать большему количеству совпадений, он должен повторять всю группу: нулевые разделители, за которыми следует один буквенно-цифровой, снова и снова. Если бы второй [a-zA-Z0-9] сопровождался знаком плюс, он мог бы найти совпадение по гораздо более прямому маршруту.

/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/

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

/^(?!.*[_\s-]{2,})[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9]$/

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

/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/

Это ваше собственное регулярное выражение, и оно требует, чтобы строка начиналась и заканчивалась двумя буквенно-цифровыми символами, а если в строке есть два разделителя, там между ними должно быть ровно два буквенно-цифровых символа. Таким образом, ab , ab-cd и ab-cd-ef будут соответствовать, но a , ab и abc не будет.

Кроме того, как отметили некоторые из комментаторов, (_ | - |) в вашем регулярном выражении должно быть [-_] . Эта часть не неверна , но если у вас есть выбор между чередованием и классом символов, вы всегда должны использовать класс символов: они более эффективны, а также более читабельны.

Опять же, Меня не беспокоит, должны ли «буквенно-цифровые» включать символы, отличные от ASCII, или точное значение «пробела», а просто как обеспечить соблюдение политики несмежных внутренних разделителей с помощью регулярного выражения.

72
ответ дан 27 November 2019 в 04:13
поделиться

По-моему, добавление ограниченного объема к этой модели было бы лучше

[a-zA-Z0-9] + ([_-]? [a-zA-Z0-9]) {5,40} $

enter image description here

0
ответ дан 27 November 2019 в 04:13
поделиться
 ([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*

- это 0 или более повторений букв, пробелов, букв.

Таким образом, он будет соответствовать

a_aa_aa_a

, но не

aaaaa

Полное регулярное выражение не может соответствовать

a_aaaaaaaaa_a for example.

Давайте посмотрим назад к тому, что вы хотите:

* Usernames can consist of lowercase and capitals or alphanumerica characters
* Usernames can consist of alphanumeric characters
* Usernames can consist of underscore and hyphens and spaces
* Cannot be two underscores, two hypens or two spaces in a row
* Cannot have a underscore, hypen or space at the start or end

Начало простое ... просто сопоставьте буквенный знак, затем (введя два правила в строке) (буквенное или тире) * и снова и снова буквенный знак.

Чтобы чтобы предотвратить два тире подряд, вам, вероятно, нужно понимать lookahead / lookbehind.

О, и что касается другого ответа: пожалуйста, скачайте Espresso, он ДЕЙСТВИТЕЛЬНО помогает вам понять эти вещи.

4
ответ дан 27 November 2019 в 04:13
поделиться
  1. Алфавитно-цифровые символы - это не просто [a-zA-Z0-9] , это акцентированные, кириллические, греческие и другие буквы, которые можно использовать в имени пользователя.

  2. (_ | - |) можно заменить на [-_] класс символов

3
ответ дан 27 November 2019 в 04:13
поделиться

Использование класса символов POSIX для буквенно-цифровых символов, чтобы заставить его работать с акцентированными и другими иностранными алфавитными символами:

/^[[:alnum:]]+([-_ ]?[[:alnum:]])*$/

Более эффективный (предотвращает захват):

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/

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

1
ответ дан 27 November 2019 в 04:13
поделиться

Еще одна рекомендация для Expresso 3.0 здесь - очень легко использовать и наращивать струны.

0
ответ дан 27 November 2019 в 04:13
поделиться

Регулярное выражение не работает. Самая сложная часть - это проверка на наличие следующих друг за другом пробелов / дефисов. Вы можете использовать это, которое использует ретроспективу:

/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
0
ответ дан 27 November 2019 в 04:13
поделиться

Судя по всему, это правило не соответствует чему-то вроде «a_bc», «ab_c», «a_b» или "a_b_c".

Попробуйте: / ^ [a-zA-Z0-9] + ([_ \ s \ -]? [a-zA-Z0-9]) * $ / что соответствует приведенным выше случаям, но не любой комбинации пробелов, тире или подчеркивания рядом друг с другом. Например: "_-" или "_" недопустимы.

1
ответ дан 27 November 2019 в 04:13
поделиться

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

3
ответ дан 27 November 2019 в 04:13
поделиться
Другие вопросы по тегам:

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