Sql 在SAS EG中提取关键字后的字符串部分

Sql 在SAS EG中提取关键字后的字符串部分,sql,sas,enterprise-guide,Sql,Sas,Enterprise Guide,我试图根据SAS eg中的关键字提取带有回车符的字符串部分 Str="started manually 23:56:22 Skipped: obtain name Completed: verify dob Skipped: ask again Skipped: verify address Completed: verify country Stopped manually 23:58:55" 我正试图根据跳过的或完成的提取部分内容。 所以,如果我要求跳过,我希望最终结果是,包括回车: O

我试图根据SAS eg中的关键字提取带有回车符的字符串部分

Str="started manually 23:56:22
Skipped: obtain name
Completed: verify dob
Skipped: ask again
Skipped: verify address 
Completed: verify country
Stopped manually 23:58:55"
我正试图根据
跳过的
完成的
提取部分内容。 所以,如果我要求跳过,我希望最终结果是,包括回车:

Obtain name
Ask again
Verify address
我想我需要循环查找跳过的每个实例。我尝试了扫描、查找、索引和SUBSTR的不同变体

我以前提取过子字符串,但仅当字符串的字符/单词位置一致时才提取。 这根绳子非常结实。任何数量的跳过或完成的项目都可能以不同的开始和结束措辞出现。
我在SASeg工作。

我不知道如何使用SAS做到这一点,但有一个建议可能是:


  • 将行制动器替换为
    “/>嗯,不确定您使用的是哪种语言,但在C#中,我会使用LINQ或break将字符串拆分为如下数组

    var myarray=str.Split(' ');
    
    然后您可以遍历数组,逐个查找各个单词,并在找到单词后返回接下来的2个索引。下面的代码输出:

    obtain name
    ask again
    verify address
    
    
    public class Program
    {
        public static void Main()
        {
            //Console.WriteLine("Hello World");
            Program.GetReturn("started manually 23:56:22 Skipped: obtain name Completed: verify dob Skipped: ask again Skipped: verify address  Completed: verify country Stopped manually 23:58:55","Skipped:");
        }
    
        public static string GetReturn(string str,string word)
        {
            string mystr="";
            var myarray=str.Split(' ');
    
            for(int i = 0; i< myarray.Length-1; i++)
            {
    
                if(myarray[i]==word)
                {
                    mystr=myarray[i+1] + " " +myarray[i+2];
                    Console.WriteLine(String.Format("{0} {1}", myarray[i+1],myarray[i+2]));
                }
            }       
    
            return mystr;
        }
    
    获取名称
    再问
    验证地址
    公共课程
    {
    公共静态void Main()
    {
    //Console.WriteLine(“你好世界”);
    Program.GetReturn(“手动启动23:56:22跳过:获取名称完成:验证dob跳过:再次询问跳过:验证地址完成:验证国家/地区手动停止23:58:55”,“跳过”);
    }
    公共静态字符串GetReturn(字符串str,字符串word)
    {
    字符串mystr=“”;
    var myarray=str.Split(“”);
    for(int i=0;i
    我相信有一个灵巧的答案,将是更优雅的,但


    在SQL中,不确定…

    这里的基本思想是使用
    调用扫描
    迭代字符串的单词,然后对其结果执行任何操作

    我在这里使用
    “|”
    作为单词分隔符,因为很难将回车输入编辑器,但如果它确实是CRs,则使用
    '0A'x
    作为单词分隔符

    data have;
      Str="started manually 23:56:22|Skipped: obtain name|Completed: verify dob|Skipped: ask again|Skipped: verify address|Completed: verify country|Stopped manually 23:58:55";
      length str_els1-str_els10  $40;
      array str_els[10] $;
    
      _pos=0;
      _count=1;
      _length=0;
    
      do _count = 1 by 1 until (_pos le 0);
        call scan(str,_count,_pos,_length,'|');
        if _pos>0 then str_els[_count] = substr(str,_pos,_length);
      end;
    
    run;
    

    您可能想做的不仅仅是将其放入一个数组中,但我认为从这里您可以了解其余部分。使用
    进行另一次扫描可能是起点。

    您没有提到是否希望这些提取作为记录,因此我的简单方法如下:

    您可以使用
    字节(10)
    模拟您的换行操作

    data a(keep=record str);
        length str $200.;
        str="started manually 23:56:22" || byte(10) ||
        "Skipped: obtain name"  || byte(10) ||
        "Completed: verify dob"  || byte(10) ||
        "Skipped: ask again"    || byte(10) ||
        "Skipped: verify address"   || byte(10) ||
        "Completed: verify country"  || byte(10) ||
        "Stopped manually 23:58:55";        
        do i=1 by 1 while(scan(str,i,byte(10)) ^=' ');
        new=scan(str,i,byte(10));
        if index(new,"Skipped")>=1 or index(new,"Completed")>=1 then
            record = scan(new,-1,":");
            else
            record = '';
        if length(record)>1 then output;
        end;
    run;
    

    数据集中的变量中是否存在带换行符的文本?是的,我将导入一个具有硬返回的excel电子表格。我将在excel中进行换行,但这需要很长的时间。我认为这样问题会更简单。您是否真的将其导入SAS,并检查变量在文本中是否有换行符t?因为您似乎还没有这样做。肯定有换行符您正在避免直接回答问题。Excel工作表中可能有换行符。但是,1)您是否已将文件导入SAS?2)您是否检查过,一旦导入SAS,文本中仍然存在换行符?如果要解决问题,请需要提供准确的信息。OP使用SAS。您当然可以执行此处列出的操作,但我认为调用扫描更容易。SAS有一个使用XML映射的本机XML读取器(可以使用XPath)当您链接到时,它工作得相当好,使用起来也非常简单。我怀疑这有点过头了。0A是换行符,0D是回车符。但是,通过alt enter插入EXCEL字段的字符是0A。
    obtain name
    ask again
    verify address
    
    
    public class Program
    {
        public static void Main()
        {
            //Console.WriteLine("Hello World");
            Program.GetReturn("started manually 23:56:22 Skipped: obtain name Completed: verify dob Skipped: ask again Skipped: verify address  Completed: verify country Stopped manually 23:58:55","Skipped:");
        }
    
        public static string GetReturn(string str,string word)
        {
            string mystr="";
            var myarray=str.Split(' ');
    
            for(int i = 0; i< myarray.Length-1; i++)
            {
    
                if(myarray[i]==word)
                {
                    mystr=myarray[i+1] + " " +myarray[i+2];
                    Console.WriteLine(String.Format("{0} {1}", myarray[i+1],myarray[i+2]));
                }
            }       
    
            return mystr;
        }
    
    data have;
      Str="started manually 23:56:22|Skipped: obtain name|Completed: verify dob|Skipped: ask again|Skipped: verify address|Completed: verify country|Stopped manually 23:58:55";
      length str_els1-str_els10  $40;
      array str_els[10] $;
    
      _pos=0;
      _count=1;
      _length=0;
    
      do _count = 1 by 1 until (_pos le 0);
        call scan(str,_count,_pos,_length,'|');
        if _pos>0 then str_els[_count] = substr(str,_pos,_length);
      end;
    
    run;
    
    data a(keep=record str);
        length str $200.;
        str="started manually 23:56:22" || byte(10) ||
        "Skipped: obtain name"  || byte(10) ||
        "Completed: verify dob"  || byte(10) ||
        "Skipped: ask again"    || byte(10) ||
        "Skipped: verify address"   || byte(10) ||
        "Completed: verify country"  || byte(10) ||
        "Stopped manually 23:58:55";        
        do i=1 by 1 while(scan(str,i,byte(10)) ^=' ');
        new=scan(str,i,byte(10));
        if index(new,"Skipped")>=1 or index(new,"Completed")>=1 then
            record = scan(new,-1,":");
            else
            record = '';
        if length(record)>1 then output;
        end;
    run;