从字符串的开头提取s表达式

时间:2016-08-30 08:41:08

标签: php regex

是否可以使用正则表达式匹配字符串开头的s-expression。就像我有这样的字符串:

(foo (bar)) "baz" "quux"

我要提取

(foo (bar))

它还应该能够从字符串中提取第一个s-expression,如下所示:

(foo (bar)) (foo bar)

(foo ")" "bar")

是否可以使用正则表达式?

2 个答案:

答案 0 :(得分:2)

如果没有转义序列,您可以使用

^(\((?>"[^"]*"|[^()]|(?1))*\))

请参阅regex demo

模式匹配:

  • ^ - 字符串开头
  • (\((?>"[^"]*"|[^()]|(?1))*\)) - 第1组,其模式将被递归,匹配
    • \( - 开场(
    • (?>"[^"]*"|[^()]|(?1))* - 零次或多次出现:
      • "[^"]*" - 以"开头的文字,后跟除"以外的零个或多个字符,以"结尾
      • | - 或
      • [^()] - 除()
      • 以外的字符
      • | - 或
      • (?1) - 整个第1组模式(递归)
  • \) - 结束)

注意:如果可以转义序列,那么正则表达式不是一个好工作。如果您将"[^"]*"替换为"[^\\"]*(?:\\.[^"\\]*)*",那会更好,但仍然不安全。

答案 1 :(得分:0)

更高效的正则表达式:

^(\([^()"]*(?:"[^"]*"[^()"]*)*(?1)*\))

Live demo

说明:

^                           # Asserts beginning of line
    (                           # Start of capturing group (1)
        \([^()"]*                   # A sequence of `(...` up to a double quotation mark or `)`
        (?:"[^"]*"[^()"]*)*         # Any string within double quotation marks
        (?1)*                       # Recurs a similar sequence of `(...`
        \)                          # End of match
    )                           # End of capturing group (1)

如果@Wiktor在评论中指出的那些模式是有效的,那么这个模式 - 无论多长 - 都可以工作并保持效率:

^(\([^()"]*(?1)*[^()"]*(?:"[^"]*"[^()"]*)*(?1)*\))

Live demo(参见引擎采取的步骤数)