【问题标题】:Hash of a cell text in Google SpreadsheetGoogle 电子表格中单元格文本的哈希值
【发布时间】:2011-12-21 02:51:39
【问题描述】:

如何计算特定单元格中文本的 MD5 或 SHA1 哈希值并将其设置为 Google 电子表格中的另一个单元格?

=ComputeMD5(A1)=ComputeSHA1(A1)这样的公式吗?

或者是否可以为此编写自定义公式?怎么样?

【问题讨论】:

    标签: google-sheets google-search-api


    【解决方案1】:

    打开Tools > Script Editor然后粘贴以下代码:

    function MD5 (input) {
      var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
      var txtHash = '';
      for (i = 0; i < rawHash.length; i++) {
        var hashVal = rawHash[i];
        if (hashVal < 0) {
          hashVal += 256;
        }
        if (hashVal.toString(16).length == 1) {
          txtHash += '0';
        }
        txtHash += hashVal.toString(16);
      }
      return txtHash;
    }
    

    之后保存脚本,然后在引用单元格时在电子表格中使用 MD5() 函数。

    此脚本基于Utilities.computeDigest() 函数。

    【讨论】:

    • 不错的答案。您可能想在函数内部的某处添加Utilities.sleep(100),以防止它在使用自动填充函数时崩溃(否则您将遇到函数调用频率的限制)
    • 我似乎无法让这与md5sum(1) 所做的相匹配;例如,cli 中的frew 给出了没有换行符的c241183cbf6766bd86061a60d6c8fe1b,但来自函数的cfb5d06a43aad502d0f6219143ba0e34
    • 这真的很有帮助。不过,hashVal += 256 似乎应该是 hashVal += 128。 Utlities.computeDigest() 返回一个字节数组。字节表示为从 -128 到 127 的整数。添加 128 会将它们转换为 0 到 256 之间的数字。
    • 我会将 Charset UTF8 添加到摘要计算中。 Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input, Utilities.Charset.UTF_8);
    【解决方案2】:

    感谢 gabhubert 提供代码。

    这是该代码的 SHA1 版本(非常简单的更改)

    function GetSHA1(input) {
      var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_1, input);
      var txtHash = '';
      for (j = 0; j <rawHash.length; j++) {
        var hashVal = rawHash[j];
        if (hashVal < 0)
          hashVal += 256; 
        if (hashVal.toString(16).length == 1)
         txtHash += "0";
        txtHash += hashVal.toString(16);
        }
      return txtHash;
    }
    

    【讨论】:

    • 这对我来说失败了,直到我将 var j 添加到循环中。也许我犯了一个错误,也许现在谷歌比写这篇文章时更严格。
    【解决方案3】:

    好的,明白了,

    需要创建自定义函数,如中所述 http://code.google.com/googleapps/appsscript/articles/custom_function.html

    然后按照中的说明使用 API http://code.google.com/googleapps/appsscript/service_utilities.html

    我需要手动输入完整的函数名称,以便在单元格中看到结果。

    以下是给出文本的 base 64 编码哈希的代码示例

    function getBase64EncodedMD5(text)
    { 
      return Utilities.base64Encode( Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, text));
    }
    

    【讨论】:

    • Base64 不是任何有意义的散列。这是一种编号系统转换。
    【解决方案4】:

    此方案与其他方案的区别在于:

    1. 它解决了上述解决方案中的一些问题,即偏移Utilities.computeDigest 的输出(偏移了 128 而不是 256)

    2. 它修复了一个问题,该问题导致一些其他解决方案通过在将其传递给 Utilities.computeDigest() 之前在 input 上调用 JSON.stringify() 为不同的输入生成相同的散列

    function MD5(input) {
      var result = "";
      var byteArray = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, JSON.stringify(input));
      for (i=0; i < byteArray.length; i++) {
        result += (byteArray[i] + 128).toString(16) + "-";
      }
      result = result.substring(result, result.length - 1); // remove trailing dash
      return result;
    }
    

    【讨论】:

      【解决方案5】:

      要获取一系列单元格的哈希值,请将其添加到 gabhubert 的函数旁边:

      function RangeGetMD5Hash(input) {
        if (input.map) {            // Test whether input is an array.
          return input.map(GetMD5Hash); // Recurse over array if so.
        } else {
          return GetMD5Hash(input)
        }
      }
      

      并以这种方式在单元格中使用它:

      =RangeGetMD5Hash(A5:X25)
      

      它返回与源一相同维度的范围,值将使用公式从单元格向下和向右展开。

      它是通用的单值函数到范围函数的转换方法(ref),并且比每个单元格的单独公式要快得多;在这种形式下,它也适用于单个单元格,因此可能值得以这种方式重写源函数。

      【讨论】:

        【解决方案6】:

        如果您想从整行中获取结果,可以使用@gabhubert 回答。来自脚本编辑器。

        function GetMD5Hash(value) {
          var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, value);
          var txtHash = '';
            for (j = 0; j <rawHash.length; j++) {
           var hashVal = rawHash[j];
            if (hashVal < 0)
              hashVal += 256; 
            if (hashVal.toString(16).length == 1)
              txtHash += "0";
            txtHash += hashVal.toString(16);
          }
            return txtHash;
        }
        
        function straightToText() {
          var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets();
          var r = 1;
          var n_rows = 9999;
          var n_cols = 1;
          var column = 1;
          var sheet = ss[0].getRange(r, column, n_rows, ncols).getValues(); // get first sheet, a1:a9999
          var results = [];
          for (var i = 0; i < sheet.length; i++) {
            var hashmd5= GetMD5Hash(sheet[i][0]);
            results.push(hashmd5);
          }
          var dest_col = 3;
          for (var j = 0; j < results.length; j++) {
            var row = j+1;
            ss[0].getRange(row, dest_col).setValue(results[j]);  // write output to c1:c9999 as text
          }  
        }
        

        然后,从“运行”菜单中,只需运行函数 straightToText() 即可获得结果,并避免对函数错误的过多调用。

        【讨论】:

        • 先让你看看我这样做的答案
        【解决方案7】:

        我正在寻找一个可以提供更短结果的选项。你怎么看待这件事?它只返回 4 个字符。不幸的是,它使用了 i's 和 o's,这可能会分别与 L's 和 0's 混淆;使用正确的字体和大写字母并不重要。

        function getShortMD5Hash(input) {
          var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
          var txtHash = '';
            for (j = 0; j < 16; j += 8) { 
            hashVal = (rawHash[j] + rawHash[j+1] + rawHash[j+2] + rawHash[j+3]) ^ (rawHash[j+4] + rawHash[j+5] + rawHash[j+6] + rawHash[j+7])
            if (hashVal < 0)
              hashVal += 1024;
            if (hashVal.toString(36).length == 1)
              txtHash += "0";
            txtHash += hashVal.toString(36);
          }
            return txtHash.toUpperCase();
          }
        

        【讨论】:

        • 我不明白 4 字节散列的用​​途。
        【解决方案8】:

        基于@gabhubert,但使用数组操作获取十六进制表示

        function sha(str){
            return Utilities
              .computeDigest(Utilities.DigestAlgorithm.SHA_1, str) // string to digested array of integers
              .map(function(val) {return val<0? val+256 : val}) // correct the offset
              .map(function(val) {return ("00" + val.toString(16)).slice(-2)}) // add padding and enconde
              .join(''); // join in a single string
        }
        

        【讨论】:

        • Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, "thisisteststring") .map(function(chr){return (chr+256).toString(16).slice(-2)}) 。加入('')
        【解决方案9】:

        我需要在一系列单元格中获取哈希,所以我这样运行它:

        function RangeSHA256(input)
        {
            return Array.isArray(input) ?
                input.map(row => row.map(cell => SHA256(cell))) :
                SHA256(input);
        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-19
          • 1970-01-01
          • 2012-06-01
          • 1970-01-01
          相关资源
          最近更新 更多