【问题标题】:Extract parts of a string after a key word in SAS EG在 SAS EG 中的关键字之后提取部分字符串
【发布时间】:2016-07-14 13:49:06
【问题描述】:

我正在尝试根据 SAS 中的关键字提取带有回车符的部分字符串,例如。

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"

我正在尝试根据SkippedCompleted 提取部分内容。 因此,如果我要求 Skipped,我希望最终结果是,包括回车:

Obtain name
Ask again
Verify address

我想我需要循环查找跳过的每个实例。我尝试了 SCAN、FIND、INDEX、SUBSTR 的不同变体。

我之前提取过子字符串,但仅当字符串在字符/单词位置一致时。 这个字符串会很大。可以使用不同的开始和结束措辞出现任何数量的跳过或完成。 我在 SASeg 工作。

【问题讨论】:

  • 数据集中的变量中是否真的有带有 LINE BREAKS 的文本?
  • 是的,我将导入一个很难返回的 Excel 电子表格。我在excel中打破了它们,但这需要很长时间。我认为这样问题会更容易。
  • 您是否将其实际导入 SAS,并检查该变量是否在文本中有换行符?因为您似乎还没有这样做。
  • 肯定有换行符
  • 您避免直接回答问题。 Excel 工作表中可能存在换行符。但是,1)您是否已将文件导入 SAS? 2)您是否检查过一旦导入SAS,文本中仍然存在换行符?如果您想解决您的问题,您需要提供准确的信息。

标签: sql sas enterprise-guide


【解决方案1】:

这里的基本思想是使用CALL SCAN 来迭代字符串的单词,然后对结果做任何你想做的事情。

我在这里使用'|' 作为单词分隔符,因为在编辑器中很难回车,但如果它真的是 CR,则使用 '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;

您可能想要做的不仅仅是将它放在一个数组中,但我认为您可以从这里找出其余的。另一个带有: 的 SCAN 可能是起点。

【讨论】:

  • 0A 是换行,0D 是回车。但是通过 alt enter 插入到 EXCEL 字段中的字符是 0A。
【解决方案2】:

嗯,不知道你用的是什么语言,但在 C# 中,我要么使用 LINQ,要么将字符串拆分成一个数组,如

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;
    }

我确信有一个 Linq 答案会更加优雅......

在 SQL 中,不确定...

【讨论】:

  • OP 正在使用 SAS。
【解决方案3】:

我不知道如何使用 SAS 执行此操作,但一个建议可能是:

  • "/&gt;&lt;Data type=" 替换线闸
  • :__blank!)替换为" value="

这将创建类似

started manually 23" value="56" value="22"/>
<Data type="Skipped" value="obtain name"/>
<Data type="Completed" value="verify dob"/>
<Data type="Skipped" value="ask again"/>
<Data type="Skipped" value="verify address "/>
<Data type="Completed" value="verify country"/>
<Data type="Stopped manually 23" value="58" value="55

将第一行替换为&lt;root&gt;,将最后一行替换为&lt;/root&gt;,即可得到

<root>
  <Data type="Skipped" value="obtain name"/>
  <Data type="Completed" value="verify dob"/>
  <Data type="Skipped" value="ask again"/>
  <Data type="Skipped" value="verify address "/>
  <Data type="Completed" value="verify country"/>
</root>

现在应该很容易用XPath like 检索您的数据

/root/Data[@type="Skipped"]

编辑

由于我不知道如何在 SAS 中使用 XPath 读取 XML,因此我正在搜索并发现: POSITION()-function in PATH-element of XML-map works in XML Mapper, but not in SAS-code

希望这会有所帮助...

【讨论】:

  • 你当然可以做你在这里列出的,虽然我认为 CALL SCAN 更容易。当您链接到 SAS 时,SAS 有一个使用 XML Maps(可以使用 XPath)的原生 XML 阅读器;它工作得很好,而且很容易使用。我怀疑这只是矫枉过正。
【解决方案4】:

您没有提及是否要将这些摘录作为记录,所以这是我的简单方法:

您可以使用byte(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;

【讨论】:

    猜你喜欢
    • 2020-11-04
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    相关资源
    最近更新 更多