在 2 个字符串片段之间查找子字符串

dan*_*lin 3 postgresql view pattern-matching postgresql-9.0

我试图在 Postgres 9.0 的 PostGIS 中填充一个视图,在这个视图中我希望它包含一个基于 2 个字符串位置的子字符串。请参阅下面的我的代码。

CREATE OR REPLACE VIEW vw_actions AS 
 SELECT ls.f_table_schema, ls.f_table_name, 
 (SELECT substr(ls.attribute_actions_text, 
 strpos(ls.attribute_actions_text, 'name="')+6, 
 strpos(ls.attribute_actions_text, '"/>') - 
 strpos(ls.attribute_actions_text, 'name="'))) AS actions
   FROM layer_styles ls;
Run Code Online (Sandbox Code Playgroud)

结果是它在使用 strpos 时不喜欢负数。我可以让它前进 6 个字符以从返回的子字符串中删除 'name="' 但不能删除 '"/>'。

它返回以下内容:

View SHED Database"/> 
Run Code Online (Sandbox Code Playgroud)

我希望它返回的地方:

View SHED Database
Run Code Online (Sandbox Code Playgroud)

任何建议将不胜感激。

补充:我发现如果我使用 9.1,我可以使用 strposrev 并且我认为以下代码会起作用:

CREATE OR REPLACE VIEW vw_actions AS 
 SELECT ls.f_table_schema, ls.f_table_name, 
 (SELECT substr(ls.attribute_actions_text::text, 
 strpos(ls.attribute_actions_text::text, 'name="'::text)+6, 
 strposrev(ls.attribute_actions_text::text, '"/>'::text)+3 - 
 strpos(ls.attribute_actions_text::text, 'name="'::text))) AS actions
   FROM layer_styles ls;
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 5

使用带有正则表达式的substring()代替:

substring(ls.attribute_actions_text FROM 'name="(.*?)"/>')
Run Code Online (Sandbox Code Playgroud)

点 ( .) 匹配任何字符,*?是0 个或多个匹配序列的非贪婪量词,括号 ( ()) 标记要返回的子字符串。

与您的代码一样,这将选择与模式匹配的第一个字符串,并且不会进一步查找。

此外,您不需要将表达式设为子查询,这只会增加开销:

CREATE OR REPLACE VIEW vw_actions AS 
SELECT ls.f_table_schema
     , ls.f_table_name
     , substring(ls.attribute_actions_text FROM 'name="(.*?)"/>') AS actions
FROM   layer_styles ls;
Run Code Online (Sandbox Code Playgroud)

快速测试用例(您应该提供):

SELECT *, substring(ls.attribute_actions_text FROM 'name="(.*?)"/>')
FROM  (
   VALUES
     ('bar name="View SHED Database"/> foo')
   , ('bar name="View SHED Database"/> fooname="View SHED Database"/>xx')
   , ('name="buntch a bull"/> fooname="View SHED Database"/>xx')
   , ('xxname="bla foo grr"/>')
   , ('')
   , (NULL)
   ) ls(attribute_actions_text)
Run Code Online (Sandbox Code Playgroud)