Почему функция PROC FCMP всегда возвращает 33 байта и больше?

StackOverflow https://stackoverflow.com/questions/1032238

  •  06-07-2019
  •  | 
  •  

Вопрос

У меня есть следующая функция, определенная через PROC FCMP. Смысл кода должен быть довольно очевидным и относительно простым. Я возвращаю значение атрибута из строки XHTML. Вот код:

proc fcmp outlib=library.funcs.crawl;
    function getAttr(htmline $, Attribute $) $;

       /*-- Find the position of the match --*/
    Pos = index( htmline , strip( Attribute )||"=" );

       /*-- Now do something about it --*/
       if pos > 0 then do;
          Value = scan( substr( htmline, Pos + length( Attribute ) + 2), 1, '"');
       end;
       else Value = "";
       return( Value);
    endsub;
run;

Независимо от того, что я делаю с оператором length или attrib, чтобы попытаться явно объявить возвращаемый тип данных, он ВСЕГДА возвращает только максимум 33 байта запрошенной строки, независимо от того, какой длины является фактическое возвращаемое значение. Это происходит независимо от того, какой атрибут я ищу. Тот же код (жестко запрограммированный) в шаге данных возвращает правильные результаты, так что это связано с PROC FCMP.

Вот шаг данных, который я использую для его тестирования (где PageSource.html - это любой html-файл, имеющий атрибуты, совместимые с xhtml - полностью заключенный в кавычки):

data TEST;
length href $200;
infile "F:\PageSource.html";

input;

htmline = _INFILE_;

href = getAttr( htmline, "href");
x = length(href);

run;

ОБНОВЛЕНИЕ: после обновления до SAS9.2 - Выпуск 2

это похоже на правильную работу.
Это было полезно?

Решение 3

В итоге я отказался от использования пошаговых функций данных, определенных в FCMP. Я не думаю, что они готовы к прайм-тайм. Я не только не смог решить проблему возврата 33 байтов, но и начал регулярно сбой SAS.

Итак, вернемся к старой доброй (десятилетней давности) технологии макросов. Это работает:

/*********************************/
/*= Macro to extract Attribute  =*/
/*= from XHTML string           =*/
/*********************************/
%macro getAttr( htmline, Attribute, NewVar );
   if index( &htmline , strip( &Attribute )||"=" ) > 0 then do;
      &NewVar = scan( substr( &htmline, index( &htmline , strip( &Attribute )||"=" ) + length( &Attribute ) + 2), 1, '"' );
   end;
%mend;

Другие советы

В этом случае элемента управления указателем ввода должно быть достаточно. надеюсь, это поможет.

/* create a test input file */
data _null_;
  file "f:\pageSource.html";
  input;
  put _infile_;
cards4;
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="w3.org/StyleSheets/TR/W3C-REC.css"; type="text/css"?>
;;;;
run;

/* extract the href attribute value, if any.                          */
/* assuming that the value and the attribute name occurs in one line. */
/* and max length is 200 chars.                                       */
data one;
  infile "f:\pageSource.html" missover;
  input @("href=") href :$200.;
  href = scan(href, 1, '"'); /* unquote */
run;

/* check */
proc print data=one;
run;
/* on lst
Obs                  href
 1
 2     w3.org/StyleSheets/TR/W3C-REC.css
*/

Я думаю, что проблема (хотя я не знаю почему) заключается в функции сканирования - похоже, это усечение ввода из substr (). Если вы извлекаете функцию substr из функции scan (), присвойте результат функции substr новой переменной, которую вы затем передадите в scan, и она, похоже, будет работать.

Вот что я запустил:

proc fcmp outlib=work.funcs.crawl;
    function getAttr(htmline $, Attribute $) $;
    length y $200;
       /*-- Find the position of the match --*/
    Pos = index( htmline , strip( Attribute )||"=" );

       /*-- Now do something about it --*/
       if pos > 0 then do;
          y=substr( htmline, Pos + length( Attribute ) + 2);
          Value = scan( y, 1, '"');       
       end;
       else Value = "";
       return( Value);
    endsub;
run;

options cmplib=work.funcs;

data TEST;
length href $200;
infile "PageSource.html";

input;

htmline = _INFILE_;
href = getAttr( htmline, "href");
x = length(href);
run;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top