如何用等长星号替换引号中的文本?

How to replace text in quotes with equal length asterisks?

如何在 SAS 中用相同长度的星号替换引号中的文本? 我的意思是,转换:

"12345"
"hi42"
'with "double" quotes'
there are 'other words' not in quotes

至:

*******
******
**********************
there are ************* not in quotes

第1,2,3,4行分别有7,6,22,13个星号。是的,引号本身也包括在内。

我试过这样的程序:

pat=prxparse('/[''"].*?["'']/');
do until(pos=0);
  call prxsubstr(pat,text,pos,len);
  if pos then substr(text,pos,len)=repeat('*',len-1);
end;

有效。
我的问题是:有没有更有效的方法来做到这一点?

首先,您的示例在第三个表达式上失败,因为它不记得开头引号是什么 - 所以它使“double”不匹配。

您可以使用 SAS 支持的反向引用解决该问题:

data have;
length text 24;
infile datalines pad;
input @1 text .;
datalines;
"12345"
"hi42"
'with "double" quotes'
there are 'other words' not in quotes
;;;;
run;
data want;
    set have;
    pat=prxparse('/([''"]).*?/');
    do until(pos=0);
      call prxsubstr(pat,text,pos,len);
      if pos then substr(text,pos,len)=repeat('*',len-1);
    end;
run;

效率方面,这在我的(相当快但不是特别快)SAS 服务器上处理 400k 记录(这 4 x 100,000)大约需要 1.5 秒。这似乎是合理的,除非您的文本更大或行数更大。另外,请注意,如果允许的话,这将在高度复杂的嵌套上失败(single-double-single 等,或者 single 中的 double-single 不会被识别,尽管它可能仍然可以很好地满足您的意图)。

但是,如果您想要最高效,正则表达式不是答案 - 使用基本文本函数效率更高。但是要完全正确更难,并且需要更多的代码,所以如果正则表达式的性能可以接受,我不建议这样做。但这是一个例子——您可能需要对其进行一些调整,并且您需要循环它以重复直到它找不到任何要替换的内容,如果根本没有引号则不执行它。这只是给出了如何使用文本函数的基本概念。

data want;
  set have;
  length text_sub ;
  _start = findc(text,'"''');
  _qchar = char(text,_start);  *Save aside which char we matched on;
  _end   = findc(text,_qchar,_start+1);  *now look for that one again anywhere after the first match; 
  to_convert = substr(text,_start,_end-_start+1);
  if _start eq 1 and _end eq length(text) then text_sub = repeat('*',_end-1);
  else if _start eq 1 then text_sub = substr(text,_end+1);
  else if _end eq length(text) then text_sub = substr(text,1,_start-1)||repeat('*',_end-_start);
  else text_sub = cat(substr(text,1,_start-1),repeat('*',_end-_start),substr(text,_end+1));
run;

我会跳过正则表达式,只使用 CALL SCAN() 代替。

所以循环查找下一个“单词”的位置。如果单词以引号开头和结尾,则用 * 替换单词。

data have;
  input string $char80. ;
cards;
"12345"
"hi42"
'with "double" quotes'
there are 'other words' not in quotes

What's going on?
;

data want;
  set have;
  position=1;
  do count=1 by 1 while(position>0);
    call scan(string,count,position,length,' ','q');
    if char(string,position) in ('"',"'")
      and char(string,position)=char(string,position+length-1)
      then substr(string,position,length) = repeat('*',length-1)
    ;
  end;
  drop position count length;
run;

结果

Obs    string

 1     *******
 2     ******
 3     **********************
 4     there are ************* not in quotes
 5
 6     What's going on?