【问题标题】:Combining awk and csum to hash a field结合 awk 和 csum 来散列一个字段
【发布时间】:2013-03-16 18:47:50
【问题描述】:

我有管道分隔的文本文件,需要特定字段或一组字段的 MD5 哈希。因为我在 AIX 上并且必须使用 csum 函数,所以我认为我不能简单地将文件和散列函数传递给 awk 以一举完成。

所以我正在编写一个脚本,它读取每一行,将要散列的字段传递给 csum,然后通过 gsub 将结果作为替换返回。 99% 的时间它似乎工作正常,但有时会因为 gsub 替换了不应该替换的东西而发生冲突。

#!/bin/ksh
rm $2 #Get rid of output file
while read line; do #loop through each line
MYFIELD=$(echo "$line" | cut -d "|" -f 6); #push the 6th field into a var
MYHASH=$(echo $MYFIELD | csum -h MD5 -); #csum will hash a string only on the stdin
echo $line | sed -e "s/$MYFIELD/${MYHASH}/g" >> $2 #gsub replaces, but not always what we want
done < $1 #read in the input file

我认为我可以使用 awk 来更新该字段。但我无法一次完成这一行。理想情况下,我希望有一个脚本允许我传递两个强制参数(infile 和 outfile),然后传递任意数量的字段位置,这些位置将被散列和替换。啦啦

foo infile.txt outfile.txt 2 6 12

这会读入 infile.txt,散列字段 2、6 和 12,然后写出到 outfile.txt。 您的建议将不胜感激

【问题讨论】:

  • 您是否尝试打印sed 行以查看参数替换是否正确完成?有人认为echo "$line \| sed -e \"s/$MYFIELD/${MYHASH}/g"
  • @fedorqui 替换似乎大部分时间都可以正常工作。它崩溃的地方是当要散列的字段包含一组与我不想散列的另一个字段匹配的字符时。例如,donthashit|foo1|bar1|foo2|bar2|hashit 将按照应有的方式散列字段 6,但 sed 在第一个字段和最后一个字段中都看到 hashit 并替换两者。这是一个问题,因为我只希望它操纵字段 6。
  • 如果你指定/g,每次找到它都会改变它。你有什么模式可以区分它们吗?
  • 我不确定我知道,但我相信在大多数(也许是所有?)情况下,冲突将与第一个字段发生冲突。由于第一个字段之前没有管道,我可以确保我只替换以管道开头的字符串。那是你开车去的地方吗?
  • 经过一些测试,我想我通过awk 得到了它。请看下面的答案。这样我们就可以只替换我们想要的字段(在这种情况下是第 6 个)。

标签: unix awk md5 delimiter


【解决方案1】:

awk怎么办?

代替

echo $line | sed -e "s/$MYFIELD/${MYHASH}/g" >> $2 #gsub replaces, but not always what we want

你可以使用

old=$MYFIELD; new=$MYHASH; echo $line | awk -F"|" -v o="$old" -v n="$new" '{OFS=FS} sub(o, n, $6) {print}' >> $2

基本上我们做的是:

  • old=$MYFIELD; new=$MYHASH 我们将要发送的参数分配给awk
  • echo $line 我们输出该行以便 awk 可以得到它。

在awk中,

  • -F"|" 定义 | 为字段分隔符。
  • -v o="$old"-v n="$new" 让 awk 使用变量 $old$new 分别将它们命名为 on
  • {OFS=FS} - 定义字段之间的分隔符。它也可以是OFS="|",但这样我们指示awk 使用我们在-F="|" 上定义的相同。保留字段分隔符以防它发生变化更加灵活。
  • sub(o, n, $6) 将变量o(即$MYFIELD)上的文本替换为变量v(即$MYHASH)上的文本,但在字段6上。李>
  • print 整行替换文字

这在您在 cmets 上给出的示例中对我有用:

old="hashit"; new="WE_DID"; echo "donthashit|foo1|bar1|foo2|bar2|hashit" | awk -F"|" -v o="$old" -v n="$new" '{OFS=FS} sub(o,n,$6) {print}'
donthashit|foo1|bar1|foo2|bar2|WE_DID

希望对你有帮助。

编辑
found a way 轻松将变量传递给awk:-v o=${variable_name}

这样,解决方案可以是:

echo $line | awk -F"|" -v o=${MYFIELD} -v n=${MYHASH} '{OFS=FS} sub(o, n, $6) {print}' >> $2

【讨论】:

  • 不错,看起来不错。你的解释特别有帮助。但是不保留分隔符;空格似乎已被替换。我会稍微修改一下
  • 你说得对,@Amw5G,我以前没见过。我刚刚编辑了我的答案以包含它的答案:我们需要使用{OFS=FS} 来定义分隔符。现在它应该可以工作了。
  • 优秀的@fedorqui ,似乎做到了。干杯!
猜你喜欢
  • 2014-01-16
  • 1970-01-01
  • 2017-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
  • 2022-01-05
  • 1970-01-01
相关资源
最近更新 更多