【问题标题】:In SAS compute an md5 hash for whole file given you have an md5 hash for each record在 SAS 中计算整个文件的 md5 哈希,因为每个记录都有一个 md5 哈希
【发布时间】:2019-07-18 12:16:04
【问题描述】:

这是我最近关于在 SAS 和 python 中计算 md5 哈希的问题的后续内容。所以,我使用的是 SAS v9.2,并且有一个 md5 散列函数,它接受一个字符串并返回一个散列。不过,我真正想要的是一种计算整个文件的哈希值的方法。鉴于我对每条记录都有一个哈希,有没有办法做到这一点,并使文件哈希与使用 python 代码获得的值匹配。以 sashelp.shoes 数据集为例,我将其导出为 CSV 文件,并手动删除了货币字段的双引号和美元以及逗号。然后我使用这个 python 代码计算了整个文件的哈希值:

filename = "f:/test/shoes.csv"
md5_hash = hashlib.md5()
with open(filename,"rb") as f:
    # Read and update hash string value in blocks of 4K
    for byte_block in iter(lambda: f.read(1024*1024),b''):
        md5_hash.update(byte_block.replace(b'\r', b'').replace(b'\n', b''))
    print(md5_hash.hexdigest())

并将此哈希作为输出返回:

f7f205b5b844bf57f5f51685969e0df0

如果有人可以在 SAS 中为该数据集复制这个最终哈希值,那就太好了。

PS 我使用的是 SAS V9.2

【问题讨论】:

  • 如果您的文件小于 32k 字节,您可以在常规数据步中执行此操作,因为字符变量(仍然!)限制为 32767 个字符。否则,您可以使用proc ds2 执行此操作,它允许更多数据类型(包括更长的字符串)。

标签: sas md5 checksum


【解决方案1】:

你有两个选择:

  • 在 SAS 中实现 MD5 算法。我知道 SHA 和 CRC 的现有实现,但我不确定 MD5。
  • 从 SAS 调用外部实用程序来计算文件的 md5 哈希值。有一个例子here

【讨论】:

  • 第二个选择不是一个选项,因为这会给我一个数据集的 SAS 内部格式的哈希值。数据集中的数据最终将作为文本文件传输到 AWS。我想要哈希来检查我们从 SAS 中提取的数据和最终在 AWS 中的数据是否相同。至于您的第一点,SAS 已经具有 MD5 功能。但是它只对字符串进行操作。我可以为数据集的每一行计算 md5 哈希。我想知道我是否可以用它来计算整个数据集的 md5 哈希
  • 您更关心从 SAS 提取的数据与原始 SAS 数据集之间的差异,还是在传输到 AWS 时引入的错误?您可以通过使用外部实用程序在上传之前和之后对导出的文件进行哈希处理来更轻松地排除后者。
  • @user2699504 您如何将其传输到 AWS?使用 AWS CLI?您可能正在尝试解决一个不需要解决的问题,因为他们无论如何都会在上传后验证文件校验和:docs.aws.amazon.com/cli/latest/topic/s3-faq.html
【解决方案2】:

我之前关于限制的说明仅适用于使用 DS1 时。 DS1 中没有长度限制。你可以试试这个,你会得到一个错误:

data test;
  length x $30000;
  x = repeat('-', 30000);
run;

data _null_;
  set test;
  format m $hex32.;
  m = md5(catx(',', x, x));
  put m=;
run;`

但是 Robert Pendridge 指出 DS2 可以解决这个问题是正确的。

%let reclen = 201; /* Length of each record */
%let records = 2000; /* Number of records */
%let totlen = %eval(&reclen * &records);

proc ds2;
data _null_;
   retain m;
   dcl char(&totlen) m;
   method run();
      dcl char(200) c;
      set shoes;
      c = catx(',',&varstr2);
      m = strip(m)|| strip(c);
   end;
   method term();
      dcl char(32) hh;
      hh = put(md5(m), $hex32.);
      put hh=;
   end;
enddata;
run;
quit;

这本质上是在做 Python 代码正在做的事情。 update 只是连接字符串并应用哈希。您可能需要稍微收紧一点以删除任何多余的空格等,但应该可以。

【讨论】:

    【解决方案3】:

    很遗憾,您不能在 DS1 中使用。原因是 SAS 允许的最大变量大小仅为 32,767 字节长。您可以将变量分组到多个变量中,但是当您尝试连接它们时(甚至直接调用 md5 函数时),它最终会截断它。您最好的选择是将输出写入外部文本文件(如下所示,基于您之前的示例)并在其上生成 md5sum。这实际上只是一个额外的步骤。您可以在 SAS 内部使用 X 命令来执行此操作(前提是您已配置为这样做)。

    filename ff "contents.txt" TERMSTR=CR;
    
    data _null_;
      set shoes end = lastrec;
      newvar2 = catx(',',&varstr2);
      file ff;
      put newvar2;
    run;
    

    【讨论】:

      猜你喜欢
      • 2021-06-19
      • 2012-04-14
      • 1970-01-01
      • 2011-12-08
      • 2015-12-18
      • 1970-01-01
      • 2012-12-02
      • 2012-08-17
      • 2017-01-27
      相关资源
      最近更新 更多