0

我将如何在缺少它的两个字段周围加上双引号?我可以在一个语句中使用 INSTR/SUBSTR/REPLACE 来完成它吗?

string := '"ES26653","ABCBEVERAGES","861526999728",606.32,"2017-01-26","2017-01-27","","",77910467,"DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OMAHA","NE","68144"';

Expected string := '"ES26653","ABCBEVERAGES","861526999728","**606.32**","2017-01-26","2017-01-27","","","**77910467**","DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OMAHA","NE","68144"';

请建议!谢谢你。

4

3 回答 3

1

此答案在这种情况下不起作用,因为某些字段包含逗号。我离开它以防它帮助其他人。

内部场的一种相当蛮力的方法是:

replace(replace(string, ',', '","'), '""', '"')

这会在逗号的两侧添加双引号,然后删除双双引号。您无需担心""。它变成""""然后回到""

这也适用于第一个和最后一个字段,但它使表达式复杂化。

于 2017-04-14T14:57:20.103 回答
0

此产品试图解决一些最终情况:

  • 解决第一个和最后一个字段的问题。这里只有最后一个字段是一种特殊情况,因为我们要注意字符串结尾$而不是逗号。
  • 空无引号字段,即前导逗号、连续逗号和尾随逗号。
  • 在表示单个双引号的字段中保留一对双引号。

SQL:

WITH orig(str) AS (
     SELECT '"ES26653","ABCBEVERAGES","861526999728",606.32,"2017-01-26","2017-01-27","","",77910467,"DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OMAHA","NE","68144"'
     FROM dual
   ),
   rpl_first(str) AS (
     SELECT REGEXP_REPLACE(str, '("(([^"]|"")*)"|([^,]*))(,|$)','"\2\4"\5') 
   FROM orig
   )
   SELECT REGEXP_REPLACE(str, '"""$','"') fixed_string
   FROM rpl_first;

该技术是找到一个带引号的字段并记住它,或者找到一个不带引号的字段并记住它,以逗号或字符串结尾并记住它。然后答案是 a"后跟一个字段",然后是终止符。

带引号的字段基本上"[^"]*"[^"]不是引号的任何字符,并且*重复零次或多次。这很复杂,因为非引号字符也可能是一对引号,因此我们需要一个 OR 构造,(|)"([^"]|"")*". 但是,我们必须只记住引号内的字段,因此添加括号,以便我们稍后可以反向引用 ie "(([^"]|"")*)"

未加引号的字段只是一个重复零次或多次的非逗号,我们想记住它([^,]*)

所以我们想找到其中任何一个,OR 构造再次 ie ("(([^"]|"")*)"|([^,]*))。后跟终止符,可以是逗号或字符串结尾,我们要记住它 ie (,|$)

现在我们可以用我们发现的用引号括起来的两种类型的字段之一替换它,然后是终止符 ie "\2\4"\5n反向引用的数量\n只是计算开括号的问题。

第二个REGEXP_REPLACE是解决我怀疑是 Oracle 错误的问题。如果最后一个字段被引用,则在字符串末尾添加一对额外的引号。这表明字符串结尾在解析时被处理了两次,这将是一个错误。然而,正则表达式处理可能是由标准库例程完成的,所以这可能是我对正则表达式规则的解释。欢迎评论。

Oracle regexp 文档可在Using Regular Expressions in Database Applications中找到。

感谢@Gary_W 提供的模板。在这里,我保留了两个单独的正则表达式块,以将我可以解释的位与我不能解释的位(错误?)分开。

于 2017-04-16T10:51:11.953 回答
0

此方法对字符串进行 2 次传递。首先查找一组双引号,后跟一个逗号,后跟一个不是双引号的字符。将它们替换为它们的组的简写,第一组,,'\1'缺少的双引号,第二组'\2'。然后再做一次,但反过来。当然,您可以嵌套 regex_replace 调用并最终得到一个大而丑陋的语句,但只需将其设为 2 个语句以便于维护。在你之后从事这个工作的人会感谢你,这已经够丑陋的了。

SQL> with orig(str) as (
     select '"ES26653","ABCBEVERAGES","861526999728",606.32,"2017-01-26","2017
-01-27","","",77910467,"DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OMAHA
","NE","68144"'
     from dual
   ),
   rpl_first(str) as (
     select regexp_replace(str, '(",)([^"])', '\1"\2')
   from orig
   )
   select regexp_replace(str, '([^"])(,")', '\1"\2') fixed_string
   from rpl_first;

FIXED_STRING
--------------------------------------------------------------------------------

"ES26653","ABCBEVERAGES","861526999728","606.32","2017-01-26","2017-01-27","",""

,"77910467","DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OMAHA","NE","681

44"


SQL>

编辑:更改了正则表达式并添加了第三步,以根据 Unoembre 的评论允许空的、未引用的字段。接得好!还添加了额外的测试用例。始终期待意外并确保为所有数据组合添加测试用例。

SQL> with orig(str) as (
        select '"ES26653","ABCBEVERAGES","861526999728",606.32,"2017-01-26","2
017-01-27","","",77910467,"DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OM
AHA","NE","68144"'
        from dual union
        select 'ES26653,"ABCBEVERAGES","861526999728"' from dual union
        select '"ES26653","ABCBEVERAGES",861526999728' from dual union
        select '1S26653,"ABCBEVERAGES",861526999728' from dual union
        select '"ES26653",,861526999728' from dual
      ),
      rpl_empty(str) as (
        select regexp_replace(str, ',,', ',"",')
        from orig
      ),
      rpl_first(str) as (
        select regexp_replace(str, '(",|^)([^"])', '\1"\2')
      from rpl_empty
      )
      select regexp_replace(str, '([^"])(,"|$)', '\1"\2') fixed_string
      from rpl_first;

FIXED_STRING
--------------------------------------------------------------------------------

"ES26653","ABCBEVERAGES","861526999728","606.32","2017-01-26","2017-01-27","",""

,"77910467","DOROTHY","","RAPP","14219 PIERCE STREET, APT1","","OMAHA","NE","681

44"

"ES26653","ABCBEVERAGES","861526999728"
"ES26653","","861526999728"
"1S26653","ABCBEVERAGES","861526999728"
"ES26653","ABCBEVERAGES","861526999728"

SQL>
于 2017-04-14T15:42:16.307 回答