Что такое регулярное выражение Perl может соответствовать словам CamelCase?

Я ищу следующие слова в файлах .todo:

ZshTabCompletionBackward 
MacTerminalIterm

Я сделал следующее регулярное выражение

[A-Z]{1}[a-z]*[A-Z]{1}[a-z]*

Однако этого недостаточно, так как он находит только следующий тип слов

ZshTab

В псевдокоде я пытаюсь сделать следующее regex

([A-Z]{1}[a-z]*[A-Z]{1}[a-z]*){1-9}

Как вы можете сделать вышеупомянутое регулярное выражение в Perl?

Ответ 1

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

/
   \b      # word boundary so you don't start in the middle of a word

   (          # open grouping
      [A-Z]      # initial uppercase
      [a-z]*     # any number of lowercase letters
   )          # end grouping

   {2,}    # quantifier: at least 2 instances, unbounded max  

   \b      # word boundary
/x

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

/\b([A-Z][a-z]*){2,}\b/

Как отмечает j_random_hacker, это немного просто, так как оно будет соответствовать слову, которое будет просто последовательными заглавными буквами. Его решение, которое я расширил с помощью /x, чтобы показать некоторые детали, обеспечивает хотя бы одну строчную букву:

/
    \b          # start at word boundary
    [A-Z]       # start with upper
    [a-zA-Z]*   # followed by any alpha

    (?:  # non-capturing grouping for alternation precedence
       [a-z][a-zA-Z]*[A-Z]   # next bit is lower, any zero or more, ending with upper
          |                     # or 
       [A-Z][a-zA-Z]*[a-z]   # next bit is upper, any zero or more, ending with lower
    )

    [a-zA-Z]*   # anything that left
    \b          # end at word 
/x

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

/\b[A-Z][a-zA-Z]*(?:[a-z][a-zA-Z]*[A-Z]|[A-Z][a-zA-Z]*[a-z])[a-zA-Z]*\b/

Я объясняю все эти функции в Learning Perl.

Ответ 2

Предполагая, что вы не используете регулярное выражение для извлечения и просто сопоставляете...

[A-Z][a-zA-Z]*

Не единственное реальное требование, чтобы все буквы писали и начинались с заглавной буквы?

Ответ 3

brian's и ответы sharth также будут сообщать слова, которые состоят исключительно из прописных букв (например, FOO). Это может быть или не быть тем, что вы хотите. Если вы хотите ограничить только слова с верблюжьей линией, содержащие хотя бы одну строчную букву, используйте:

/\b[A-Z][a-zA-Z]*[a-z][a-zA-Z]*\b/

Если вы хотите исключить слова, состоящие из одной прописной буквы, за которой следует любое количество строчных букв (например, Perl), используйте:

/\b[A-Z][a-zA-Z]*(?:[a-z][a-zA-Z]*[A-Z]|[A-Z][a-zA-Z]*[a-z])[a-zA-Z]*\b/

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

Ответ 4

Как насчет этого: /\b[A-Z]([a-z]+[A-Z]?)*\b/??