SAS извлекает часть текста - PullRequest
       8

SAS извлекает часть текста

1 голос
/ 15 октября 2019

У меня есть три версии одной и той же строки:

 "123 aa456 aa678"
 "123 aa99 aa678"
 "45 aa28 aa234" 

Как извлечь только значения между aa ?

Я пытаюсьс if length(string)>15 then string=substr(string,8,8), но это только для первых версий ...

Ответы [ 4 ]

1 голос
/ 15 октября 2019

Предположим, что данные для анализа находятся в переменной (или _infile_).

Цикл с SCAN критерием завершения может извлекать текстовые сегменты (слова) между разделителями - потому что ваш строковый разделитель'aa' функция SCAN может использовать букву 'a' в качестве разделителя символов (поскольку операция SCAN по умолчанию заключается в том, что пустое поле между соседними разделителями ('aa') не считается извлекаемым фрагментом.

Каждыйизвлеченный фрагмент текста можно преобразовать в числовое значение с помощью функции INPUT.

Если вы не знаете, сколько элементов можно отсканировать, сначала выведите «вертикальный» список и транспонируйте его.

data lines;
  input;
  line = _infile_;
datalines;
123 aa456 aa678
123 aa99 aa678
45 aa28 aa234
45 aa28 aa234 aa 999
45 aa this is wrong aa -234 aa 999
run;

data ids;
  set lines;

  rownum + 1;
  do _n_ = 1 by 1 while (scan(line, _n_, 'a') ne '');
    id = input ( scan(line, _n_, 'a'), ??best12. );
    output;
  end;
run;

proc transpose data=ids out=want(drop=_name_) prefix=id;
  by rownum;
  var id;
run;

Создает вывод

rownum    id1    id2     id3    id4

   1      123    456     678      .
   2      123     99     678      .
   3       45     28     234      .
   4       45     28     234    999
   5       45      .    -234    999
1 голос
/ 15 октября 2019

Вы можете использовать функцию prxnext (двенадцатая страница здесь ). В вашем случае это будет выглядеть (вам нужно инициализировать num значений, в моем примере это 3):

data have;
 string =  "123 aa456 aa678";
 output;
 string =  "123 aa99 aa678";
 output;
 string =  "45 aa28 aa234";
 output; 
run;


data check_next(keep=id: string);
    array ids{3} id1-id3;
    set have;
    if _n_=1 then do;
       retain re;
       re = prxparse('/[\d]+/');
       if missing(re) then do;
          putlog 'ERROR: a regex is malformed';
          stop;
       end;
    end;
    start = 1;
    stop = length(string);
    call prxnext(re,start,stop,string,startposn,len);
    do i = 1 to 3 while(startposn > 0);
       ids{i} = input(substr(string,startposn,len),5.);
       call prxnext(re,start,stop,string,startposn,len);
    end;
run;

Иметь набор данных:

+=================+
|     string      |
+=================+
| 123 aa456 aa678 |
+-----------------+
| 123 aa99 aa678  |
+-----------------+
| 45 aa28 aa234   |
+-----------------+

Набор данных Check_next:

+=====+=====+=====+=================+
| id1 | id2 | id3 |     string      |
+=====+=====+=====+=================+
| 123 | 456 | 678 | 123 aa456 aa678 |
+-----+-----+-----+-----------------+
| 123 |  99 | 678 | 123 aa99 aa678  |
+-----+-----+-----+-----------------+
|  45 |  28 | 234 | 45 aa28 aa234   |
+-----+-----+-----+-----------------+
1 голос
/ 15 октября 2019

Пример опции оператора DLMSTR INFILE.

data test;
   infile cards dlmstr=' aa';
   input v1-v3;
   line = _infile_;
   cards;
123 aa456 aa678 
123 aa99 aa678
45 aa28 aa234
;;;;
   run;

enter image description here

1 голос
/ 15 октября 2019

Вы можете использовать функции find + substr:

data g;
d= "123 aa456 aa678";
d_pos1=find(d,"aa");
d_pos2=find(d,"aa",d_pos1+2);
d_between_aa1=substr(d,d_pos1+2,d_pos2-d_pos1-2);
run;

Или использовать функции prx:

data g;
d= "123 aa456 aa678";

re= prxparse('/aa([\w\d\s\t]*)aa/');
pos = prxmatch(re, d) ;
text = prxposn(re, 1, d) ;
run;
...