2016-08-29 39 views
0

正如我們所知,在宏編譯過程中應該隱藏特殊字符。但是如果我想將一個動態子串分配給一個宏變量呢?像這樣:將一個子字符串(可能包含引號等)傳遞給宏變量

%let mvSubstr = %substr(&mvString, 1, 1); 

mvString可以包含任何符號,包括不匹配的單引號或雙引號。

所以,在這個例子程序正常工作:

%lev mvString = Test; 
%let mvSubstr = %substr(&mvString, 1, 1); 

並在以下情況下,程序不能正常工作和SAS報告ERROR: Literal contains unmatched quote.

%lev mvString = %str(%'Test%'); 
%let mvSubstr = %substr(&mvString, 1, 1); 

我怎樣才能戰勝這個問題(請程序獨立於mvString值)?

回答

4

如果你希望它是可能的子串的值使用%QSUBSTR()功能將包含不匹配的引號或需要宏引用的其他字符。當使用%SCAN()的結果可能需要引用時,也會使用%QSCAN()函數。從宏代碼中調用其他SAS函數時有%QSYSFUNC()函數。

3

這就是爲什麼macro quoting存在。你有很多不同的選擇,具體取決於你在做什麼。

  • %quote%nrquote%bquote,並%nrbquote - 所有做大致相同的事情:面具引號字符和其他一些特殊字符。例如參見documentation for %bquote/nrbquote。他們告訴SAS不要注意'和類似的東西,所以它不用擔心匹配的東西。我從來沒有見過使用%quote而不是%bquote的理由--B代表「更好」 - 所以我會使用它。他們在執行期間工作,而不是彙編%nrbquote掩蓋宏字符&%,這意味着它將阻止宏變量內的宏解析。
  • %str and %nrstr mask 彙編。否則它們與%bquote%nrbquote相似。如果在編譯過程中沒有引用是很重要的,請使用它們。
  • %superq僅屏蔽了一個宏變量(未打開文本)並防止發生所有分辨率。將一個宏變量的值分配給另一個變量通常是最好的方法。重要的是不要採用&--你通過宏變量的名稱,沒有&符或什麼都不(除非宏變量的名稱存儲在另一個宏變量中)。

在你的情況,你就需要使用%bquote引用的子任務的結果,所以:

%let mvString = %str(%'Test%'); 
%put &=mvString; 

%let mvSubstr = %bquote(%substr(&mvString, 1, 1)); 
%put &=mvString &=mvSubstr; 
+0

聽起來像只是使用爲這種情況構建的函數做了很多額外的工作。 – Tom

+0

不確定是否有很多額外的工作(一個宏語句?)...'qsubstr'雖然很好,我還沒有看到。 – Joe

+0

'%QSUBSTR()'和'%QSCAN()'是最初幾個宏函數的一部分。當他們引入'%SYSFUNC()'時,出於同樣的原因,他們包含'%QSYSFUNC()'。 – Tom

1

如果MVSTRING包含需要特殊處理的未掩碼字符,情況如何?這需要引用SUBSTR的參數。

data _null_; 
    call symputx('mvString',"'Test",'G'); 
    run; 
%put %nrbquote(&=mvString); 
%let mvSubstr = %bquote(%substr(%superq(mvString), 1, 1)); 
%put %nrbquote(&=mvString) %nrbquote(&=mvSubstr); 
+0

同意 - 我曾考慮過提及那個,但想簡化我的答案。絕對是一個好主意來考慮輸入(以及不同報價選項的差異的一個很好的例子)。 – Joe

+0

這是一種不同的情況。如果SAS具有可創建宏引用宏變量的數據步功能,那將會很不錯。現在,您可以添加%LET,以在數據步驟創建後應用引用。 – Tom

+0

@Tom我認爲'%superq'解決方案更加優越 - 假設你的數據在編寫你的函數/程序時可能沒有被適當地引用,並且防止這種情況發生。在創建過程中另外引用它,但我不認爲這就是DN在這裏的例子(這就是他如何得到一個沒有引號的值)。 – Joe

相關問題