Oracle正则表达式寻找空间或字符串结尾

时间:2012-06-19 18:47:09

标签: regex oracle

我正在处理一个验证法律描述中的quarter数据的查询。我们的标准输入如“SE / 4”标记东南区或“SE / 4 NW / 4”标记西北区的东南区。我正在努力解决如何通过正则表达式构造来检查字符串的空格或结尾。

到目前为止,这是我的正则表达式的一些示例数据。

WITH test_data AS (
  SELECT 'NW/4' AS quarter_cd FROM dual UNION ALL --VALID
  SELECT 'E/2 SW/4' FROM dual UNION ALL           --VALID
  SELECT 'W/2' FROM dual UNION ALL                --VALID
  SELECT 'SW/4 NE/4' FROM dual UNION ALL          --VALID
  SELECT 'SW/4 NE/4 NW/4' FROM dual UNION ALL     --VALID, THEY CAN REPEAT AN UNKNOWN NUMBER OF TIMES
  SELECT 'E/2 N/2' FROM dual UNION ALL            --TECHNICALLY VALID BUT WOULD LIKE TO EXCLUDE (1/2 of 1/2 is a 1/4) -> NE/4
  SELECT 'E/2 SW/4, SE/4' FROM dual UNION ALL     --INVALID, HAS A COMMA (TWO QUARTER ENTRIES ON ONE ROW)
  SELECT 'E/2 SW/4 & SE/4' FROM dual UNION ALL    --INVALID, HAS AN AMPERSAND (TWO QUARTER ENTRIES ON ONE ROW)
  SELECT 'E/2 SW/' FROM dual UNION ALL            --INVALID, INCOMPLETE ENTRY
  SELECT 'SE/4SW/4' FROM dual UNION ALL           --INVALID, NO SPACE BETWEEN DEFINITIONS
  SELECT 'SE/2' FROM dual UNION ALL               --INVALID, SOUTHEAST HALF DOES NOT MAKE SENSE
  SELECT 'N/4' FROM dual UNION ALL                --INVALID, NORTH QUARTER DOES NOT MAKE SENSE
  SELECT 'LOT 1' FROM dual                        --INVALID, LOTS WILL BE DEALT WITH SEPARATELY
)
SELECT * FROM test_data 
WHERE regexp_like(quarter_cd, '^([NSEW]/[2]{1}|[NSEW]{2}/[4]{1})+', 'c');

我的代码中的正则表达式只是我多次尝试中的一个。我在查询中标记了应该返回的结果。为了简单起见,我愿意让“E / 2 N / 2”返回,虽然技术上它是无效的,因为北半部的东半部最好简化到东北区。上面的所有示例都是从我的数据中的实际条目中提取的。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:2)

这是我的低调尝试:

select *
  from test_data
 where regexp_like(quarter_cd
        , '^((([NSEW]{1}/2)|[NS]{1}[EW]{1}/4)([[:space:]]|$))+$'
        , 'c')

它确实会回归E/2 N/2

  • 允许其中一个N S E W后跟2
  • N S E W中的一个,然后是4
  • 必须后跟空格或行尾
  • 允许此项贪婪地匹配
  • 必须以行尾结束

通过拆分你的[NSEW],它排除了NS或EW等的匹配。

这是一个SQL Fiddle来演示。我已经在你自己的基础上增加了几个额外的案例。这个问题是它将允许所有四个半部分。

我会认真考虑 not 使用正则表达式来验证此数据。而是通过PL / SQL函数传递它。拆分空间并添加你必须检查你没有超过限制。然后,您可以使用较小的正则表达式来验证空格分隔符之间的基础数据。

答案 1 :(得分:1)

我认为这样的事情会给你你想要的东西:

SELECT * FROM 
  test_data 
WHERE 
  regexp_like(quarter_cd, 
  '^([NSEW]/[2]{1}|[NSEW]{2}/[4]{1})( [NSEW]/[2]{1}| [NSEW]{2}/[4]{1})*$', 'c');

但它会匹配“E2 / N2”的情况。如果你这样做:

SELECT * FROM 
  test_data 
WHERE 
  regexp_like(quarter_cd, 
  '^([NSEW]/[2]{1}|[NSEW]{2}/[4]{1})( [NSEW]{2}/[4]{1})*$', 'c');

然后它将不匹配,但它也不匹配任何包含初始位置后的[NSEW] / 2的情况。所以如果你需要匹配,那就不太好了,比如“NW / 4 E / 2”......西北区的东半部。