简体   繁体   English

如何捕获正则表达式的首次出现并使用PostgreSQL插入到字符串中

[英]How to capture regex first occurence and interpolate into string with postgreSQL

I'm trying to concatenate the digits from a string that starts with 'CityName' into a separate string. 我正在尝试将以“ CityName”开头的字符串中的数字连接成一个单独的字符串。 I have the concatenation part. 我有串联部分。 My issue is being able to access the matches from the regex I have a regex in rails that looks like /CityName\\s*(\\d+)/i . 我的问题是能够从正则表达式访问匹配项,我在rails中有一个正则表达式,看起来像/CityName\\s*(\\d+)/i I'm super new to regex and it's hard for me to wrap my head around the docs. 我是regex的新手,我很难把头围在文档上。 But I'm assuming that this regex will find any digits after the CityName case intensively. 但是我假设此正则表达式将在CityName案例后集中找到任何数字。 And then it's interpolated if it matches an attribute on my model. 然后,如果它与我的模型上的属性匹配,则会对其进行插值。

regex = /CityName\s*(\d+)/i
if line_1 =~ regex
  "C#{$1}"
  ...
end

But further along in the execution, it's slowing down because I have to iterate over a lot of records. 但是在执行过程中,由于我必须遍历许多记录,因此它的速度正在减慢。 I have a query in psql that will do that calculations that I need, however I'm having a hard time implementing this regex replacement. 我在psql中有一个查询,它将执行我需要的计算,但是我很难实现此正则表达式替换。 My attempts so far look like: 到目前为止,我的尝试如下:

CASE
    when addr.line_1 ~* 'CityName\s*(\d+)' then 'C' || regex_matches('CityName\s*(\d+)')[0]
...

I'm having a hard time finding a solution to grab the first occurrence of the regex match. 我很难找到一种解决方案来抓住第一次出现的正则表达式匹配项。 Thanks for any tips :D 谢谢你的提示:D

EDIT: I am trying to grab the digits after 'CityName' from a string if that string contains 'CityName' Ultimately I need assistance with the regex and how to contactenate the digits with 'C' 编辑:如果该字符串包含“ CityName”,我试图从字符串中获取“ CityName”之后的数字最终,我需要使用正则表达式以及如何用“ C”联系数字的帮助

Your question is a bit unclear. 您的问题还不清楚。 Are you trying to add the digits to your selection or to filter records based on them? 您是要添加数字到您的选择中还是要基于数字过滤记录?

If you just want to select them: 如果只想选择它们:

Address.select(%q{(regexp_matches(addr.line_1, 'CityName\s*(\d+)'))[1] as digits})
  .map(&:digits)

If you want to filter based on then: 如果要基于以下条件进行过滤:

Address.where(%q{addr.line_1 ~ 'CityName\s*(\d+)'}).map &:email
  .map(&:line_1)

Also a few notes: 还有一些注意事项:

  • Selecting digits case intensively does not really make sense. 严格选择数字大小写并没有任何意义。 Digits does not have case. 数字没有大小写。
  • PostgreSQL arrays start from 1 instead of 0. PostgreSQL数组从1而不是0开始。

Got it! 得到它了! Was able to finally start to figure out the regex. 终于能够弄清楚正则表达式。 WHEN addr.line_1 ~* '(?i)CityName\\s*(\\d+)' THEN 'C' || (SELECT (regexp_matches(addr.line_1, '(?i)CityName\\s*(\\d+)'))[1]) WHEN addr.line_1 ~* '(?i)CityName\\s*(\\d+)' THEN 'C' || (SELECT (regexp_matches(addr.line_1, '(?i)CityName\\s*(\\d+)'))[1]) The (?i) allowed for case insensitive matching for CityName and then the concatenation worked. WHEN addr.line_1 ~* '(?i)CityName\\s*(\\d+)' THEN 'C' || (SELECT (regexp_matches(addr.line_1, '(?i)CityName\\s*(\\d+)'))[1]) (?i)允许对CityName进行不区分大小写的匹配,然后进行串联。 Thank you @ti6on for pointing out the index difference with postgres :D 感谢@ ti6on指出与postgres的索引差异:D

It seems you need a subquery or a WITH query: 看来您需要子查询或WITH查询:

SELECT tbl1.col1, sum(...), min(...) FROM (SELECT ..., CASE ...yourregex stuff... END col1 FROM ...) tbl1 GROUP BY 1;

WITH tbl1 AS (SELECT ..., CASE ...yourregex stuff... END col1 FROM ...) SELECT t.col1, sum(...) FROM tbl1 t GROUP BY 1;

If you need them regulary, you can also create views from the query or create a temp table, then you can use it in queries later. 如果经常需要它们,则还可以从查询中创建视图或创建临时表,然后可以在以后的查询中使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM