在PRX函数处理前转义数值的函数?

huangapple go评论69阅读模式
英文:

Function to escape value before PRX function processing?

问题

我正在使用(大量)prx函数(Perl正则表达式函数),但在某些情况下,我会在宏函数中使用它们,并将某些内容作为参数传递进行搜索,例如:

%macro test(exp=);
  proc sql noprint;
    select      file
    into        :_input_file trimmed
    from        folder_content
    where       prxmatch("/&exp.$/oi", strip(file))
    ;
  quit;
%mend test

在大多数情况下,这种方法有效,但当exp的值包含PRX元字符(例如/或括号)时除外。

良好的做法是转义这些字符,但这并不用户友好。比如说,如果我想搜索一个文件/home/user/file.txt,斜杠会导致宏失败,而我应该传递值\/home\/user\/file.txt

在实现自己的转义函数之前,我想确保它是否已经存在,但我迄今为止还没有找到它。

我期望有一个原生的SAS函数可以将任何文本值转换为在PRX函数中“ready to use”的值。

英文:

I'm using (a lot) prx functions (Perl Regular eXpression functions), however in some cases, I use them within a macro function and pass something to search as a parameter, e.g.

%macro test(exp=);
  proc sql noprint;
    select      file
    into        :_input_file trimmed
    from        folder_content
    where       prxmatch("/&exp.$/oi", strip(file))
    ;
  quit;
%mend test

In most cases, this works, except when the value of exp contains PRX metacharacter (e.g. / or parenthesis)

The good practice is to escape such characters, but that's not user friendly.
Let's say I want to search a file /home/user/file.txt, the slashes will make cause the macro to fail, instead I should pass the value \/home\/user\/file.txt

Before implementing my own escaping function, I want to ensure it does not already exist, but I've not been able to find it so far

I expect a **native **SAS function to convert any text value into a "ready to use" value within a PRX function

答案1

得分: 1

The / is an implicit m/ for matching. The first character after m is the expression bounder. So, use an initial character such as #. "#&exp.$#oi" - any / in the resolved &exp will be treated as literal /

Mixing regex patterns with macro can be very frustrating and a seeming endless pit of escapism. Consider treating your patterns as data and join them to the data set of concern. Bonus is no macro.

  rx = '....'; output;
  rx = '....'; output;
  ...
run;  

proc sql noprint;
  create table matches as 
  select      file
  from        folder_content
  join        mypatterns p
    on        prxmatch (strip(p.rx),strip(file))
  ;
quit;
英文:

The / is an implicit m/ for matching. The first character after m is the expression bounder. So, use an initial character such as #. "#&exp.$#oi" - any / in the resolved &exp will be treated as literal /

Mixing regex patterns with macro can be very frustrating and a seeming endless pit of escapism. Consider treating your patterns as data and join them to the data set of concern. Bonus is no macro.

data mypatterns;
  rx = '....'; output;
  rx = '....'; output;
  ...
run;  

proc sql noprint;
  create table matches as 
  select      file
  from        folder_content
  join        mypatterns p
    on        prxmatch (strip(p.rx),strip(file))
  ;
quit;

答案2

得分: 1

以下是翻译好的内容:

没有像您请求的那样的函数(我甚至不确定我能理解这样一个函数应该做什么)。

但对于您只想将值视为字符串的示例(即不是实际的正则表达式),则没有太多需要发生的事情。

  • 将任何现有的 \ 转换为 \\ 以防止它们被用于转义下一个字符。
  • 在使用分隔符的任何出现位置(在您的示例中是 /)添加 \ 以进行转义。

所以如果您有名为 EXP 的宏变量

%let exp=c:\mixed_up/path ;

您可以将其转换为您可以在 WHERE 子句中使用的内容

%let want=%qsysfunc(tranwrd(%superq(exp),,\));
%let want=%qsysfunc(tranwrd(&want,/,/));

这将创建:

650 %put &=want;
WANT=c:\mixed_up/path

英文:

There is no function like you requested (I am not even sure I could understand what such a function would be expected to do).

But for your example of just wanting the treat the value as a STRING (ie not an actual regular expression) then there is not much that needs to happen.

  • Convert any existing \ to \\ to prevent them from being used to escape the next character.
  • Add \ to any occurrence of the separator you are using (in your example the /) to escape it.

So if you have macro variable named EXP

%let exp=c:\mixed_up/path ;

You can convert it to something you could use in your WHERE clause

%let want=%qsysfunc(tranwrd(%superq(exp),\,\\));
%let want=%qsysfunc(tranwrd(&want,/,\/));

Which will create:

650  %put &=want;
WANT=c:\\mixed_up\/path

答案3

得分: 0

Use something other than /

13 data null;
14 x = 'MCLAUREN';
15 x = prxchange("s!(MC)!\u\L$1!i", -1, x);
16 put x=;
17 x = prxchange("s/(MC)/\u\L$1/i", -1, x);
18 put x=;
19 run;

x=McLAUREN
x=McLAUREN

英文:

Use something other than /

13   data _null_;
14      x = 'MCLAUREN';
15      x = prxchange("s!(MC)!\u\L$1!i", -1, x);
16      put x=;
17      x = prxchange("s/(MC)/\u\L$1/i", -1, x);
18      put x=;
19   run;

x=McLAUREN
x=McLAUREN

huangapple
  • 本文由 发表于 2023年6月27日 21:23:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定