Verifying that a string does not contain curly brackets other than those used for formatting

StackOverflow https://stackoverflow.com/questions/22788941

I am trying to build a function which verifies that a string does not contain curly brackets ({ and }), other than those which may be used for one-level formatting. That is, I wish to allow curly brackets which may vanish after a single call to the .format method of the string.

For example, if this verification function is called no_curly_braces, the following results should be returned:

>>> no_curly_brackets("word")
True
>>> no_curly_brackets("{word")  # False, as .format raises ValueError
False
>>> no_curly_brackets("{}word")  # True, as .format(3) returns '3word'
True
>>> no_curly_brackets("{word}")  # True, as .format(word=3) returns '3'
True
>>> no_curly_brackets("{{word}}")  # False, as .format returns '{word}'
False
>>> no_curly_brackets("{{{word}}}")  # False, as .format(word='a') returns '{a}'
False
>>> no_curly_brackets("{word}{{}}")  # False, as .format(word=3) returns '3{}'
False

and so on.

My problem is that attempts like "{" in str will fail (as templates may hold these curly brackets), and I cannot wish to format without knowing what I should provide to the .format method, in order to try to make the relevant curly brackets vanish.

有帮助吗?

解决方案

Use the string.Formatter() class:

from string import Formatter

def no_curly_brackets(fmt):
    try:
        parsed = Formatter().parse(fmt)
        return not any('{' in lt or '}' in lt for lt, _, _, _ in parsed)
    except ValueError:
        return False

Basically anything that's parsable as a format and doesn't contain a curly brace in the parsed literal text would be True.

This matches all your test cases:

>>> for test in tests:
...     print test, no_curly_brackets(test)
... 
word True
{word False
{}word True
{word} True
{{word}} False
{{{word}}} False
{word}{{}} False

plus a few of my own:

>>> no_curly_brackets('word}}')
False
>>> no_curly_brackets('{{word')
False
>>> no_curly_brackets('word{{}}')
False

其他提示

Here's an answer based on my comment above:

def no_curly_brackets(fmt):
  n = 0
  for c in fmt:
    if c == '{':
      n=n+1
    elif c == '}':
      n=n-1
    if n < 0 or n > 1:
      return False
  return (n == 0)

Some sample results:

word True
{word False
{}word True
{word} True
{{word}} False
{{{word}}} False
{word}{{}} False
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top