2018年7月19日 星期四

Non printable 字元

問題:有特殊 ASCII 字碼存在資料裡面,而且用 print 也看不見,會造成資料 compare 不一致,或者 ods 輸出會出現莫名的換行或符號
解決:
可以先了解有哪些 non-printable 的字碼,可參考
ascii-table

ASCII extended sets characters 有兩種編碼

  • 十進位編碼 0 to 255 (decimal values)
  • 六進位編碼 00 to FF (hexadecimal values)

但一般的 ASCII table (不含extended sets) 是 0 to 127
因此前 33 個 (0 to 32) and character 127 are the non-printable characters

例如: HT ( Horizontal Tabulation )
就是鍵盤上的 tab
用十進位編碼來看是 9 號,可按鍵盤 tab 或者 ALT 數字鍵盤9
用六進位編碼是 09 ,在 SAS 裡用 '09'x

反過來說,要看變項值的 Hexadecimal

data a; a='!'; put a= a hex. ; run; 

第一、要檢查出來

  • 用 sas function 的 NOTPRINT(string <,start>) 如果是 NOTPRINT 回傳 1

依SAS原廠的範例,來看 132, 127254 被 NOTPRINT 定義為 non-printable

data test; 
  do dec=0 to 255;  
    byte=byte(dec);  
    hex=put(dec,hex2.);  
    notprint=notprint(byte);  
    output;  
  end;  

proc print data=test; run;

ref: SAS(R) 9.2 Language Reference: Dictionary, Fourth Edition

  • 用 prxmatch 等搜尋去找。 regular expression 輸入 hexadecimal values 是用 \x00

    data test2; set test;
    byte_re=put(byte, $hex2.);
    kk=prxmatch("/00|01|02|03|04|05|06|07|08|09|0A/", byte_re);
    kk2=find(byte,'00'x);
    kk3=prxmatch("/[^\x00\t\x20-\x7E]/", byte); /自定義查找/
    run;

第二、進行轉換

  • translate 取代1個字,就會留下1個位置,即原本9個不能換成8個。
    更可以1次把多個字作取代 f2_translate=translate(f1,' ','000102030405060708090A'x);

  • tranwrd 類似 translate 但只能1次換1個。

  • transtrn 1次換1個,但可以原本9個換成8個。

    data example;
    length f1 f2_translate f3_tranwrd f4_transtrn $20;
    f1 = cat('Part1','0A'x,'Part2');
    f2_translate = translate(f1,' ','0A'x);
    f3_tranwrd = tranwrd(f1,'0A'x,' ');
    f4_transtrn = transtrn(f1,'0A'x,trimn(''));
    run;

ref: https://programmer-pro.com/special-character-sas-hex/