【问题标题】:How do I replace the value of a specific xml tag with the hashed value?如何用散列值替换特定 xml 标记的值?
【发布时间】:2018-09-08 04:05:06
【问题描述】:

我有几个压缩的 xml 文件,其中包含存储在 Trans xml 标记中的事务。其中一些交易(不是全部!)包含<customer> xml 标签,其中包含custnumber xml 标签。我需要在 xml 文件中匿名化此客户编号,以便将 xml 文件用于开发目的。 xml的结构是这样的:

<transactions>
  <trans>
  ...
    <customer>
    ...
      <customer_custnumber>123456789</customer_custnumber>
    ...
    </customer>
    ...
  </tran>
</transactions>

由于我的下游流程,我需要在散列时保留客户编号的最大长度。为此,我使用 java 编写了一个工具,该工具将客户编号散列为特定数字范围内的唯一散列。

我的第一种方法是使用从 xml 文件中读取所有客户编号,并在每次出现时调用我的哈希工具。这需要很长时间,因为我每个文件调用 java 工具 5000 次,导致每个文件的运行时间为 5-6 分钟(我每天有超过 40 个文件)。

我的第二个方法是使用 zgrepawk 按照它们在 xml 文件中出现的顺序提取所有客户编号,将它们写入文本文件并运行我的 java 工具来散列文件的每一行。这明显更快,因为 5000 个数字只需要几秒钟。但现在我的问题是用文本文件中的散列值替换客户编号的原始值。我知道它们是有序的,所以 xml 文件中的第一次出现与文本文件中的第一个哈希值有关,依此类推。但是我现在如何替换它?

这是我当前的代码:

#!/bin/bash

tempFile=cardNumber_tmp.txt
hashedTempFile=hashed_cardNumber_tmp.txt

for file in ${DIR_SRC}/input.xml.zip ; do
    declare listOfIds
    listOfIds=$(zgrep "<customer_custnumber>" $file | awk -F">" '{print $2}' | awk -F"<" '{print $1}') 
    # $listOfIds contains all Ids separated whitespaces
    # use tr to replace whitespace with newline 
    echo $listOfIds | tr " " "\n" > ${DIR_TEMP}/${tempFile} 
    # call HashCustNumber.jar for tempFile with type customer
    java -jar HashCustNumber.jar "${DIR_TEMP}/${tempFile}" "customer"
    # HashCustNumber.jar writes result into $hashedTempFile
    declare -a arr
    readarray -t arr < "${DIR_TEMP}/${hashedTempFile}"
    # Array arr contains Hashes without newline

    # ??

done

# delete tempFiles
rm ${DIR_TEMP}/${tempFile} 
rm ${DIR_TEMP}/${hashedTempFile}

我还读到我不应该使用 sed 或 awk 从 xml 文件中提取数据,并且我无法使用 xmlstarlet,因为它没有安装在我的公司服务器上。任何想法如何以不涉及散列程序的数千次调用的方式将值替换为散列值?

【问题讨论】:

  • 我可以假设客户编号是唯一的吗?然后将您的 java 输出稍微修改为:customer-number:hash_value,每行一个。然后循环这些行,剪切: 并使用 sed 或 awk 将客户编号替换为 has_value。是的,在处理 XML 时最好不要使用这些,但如果您无法访问 XML 解析器工具,那么这是您能做的最好的事情。但是,如果您对 Java “流利”,那为什么不使用 Java 做所有事情呢? XML 解析器存在于 Java 中,对您来说可能更简单。

标签: bash shell unix


【解决方案1】:

由于哈希函数是用 java 编写的,因此更有效的是使用 zip api 和 jaxp/sax 在 java 中完成整个过程。

否则,为每个 id 启动一个 jvm 是很昂贵的。此外,zgrep 只是一个使用 gzip 和 grep 的脚本,不应该与 .zip 文件一起使用。

  • 先解压,到工作目录,最后重新压缩
  • 然后假设您的 id 列表在文件 "$num_file" 中,并且要修改的文件 解压缩"$xml_file" 和目标文件 "$new_xml_file" ;替换可以使用以下 perl 命令完成

perl -pe '
    开始{
            $num_file = 转移@ARGV;
            {
                本地@ARGV = $num_file;
                @ids = 地图 {chomp;$_} ;
            }
        }
        s/\K[^ "$new_xml_file"

请注意,之前的 awk 命令用于提取数字,它是“as”安全的,因为 perl 使用相同的表达式

【讨论】:

  • 按照您的建议,我完全切换到了 java。由于压缩和解压缩,它并不是真的很快,但最终足够快可以使用。 java 程序获取 zip 文件,替换值并写入一个新的 zip 文件。
猜你喜欢
  • 2017-11-02
  • 2011-01-07
  • 2013-02-19
  • 2013-05-04
  • 2023-03-28
  • 2013-11-19
  • 2021-05-18
  • 2019-01-09
  • 1970-01-01
相关资源
最近更新 更多