Unix 结合awk和csum对字段进行散列

Unix 结合awk和csum对字段进行散列,unix,awk,md5,delimiter,Unix,Awk,Md5,Delimiter,我有管道分隔的文本文件,它需要一个特定字段或一组字段的MD5散列。因为我在AIX上,必须使用csum函数,所以我不认为我可以简单地将文件和哈希函数传递给awk来一次性完成 因此,我正在编写一个脚本,它读取每一行,将要散列的字段传递给csum,然后通过gsub将结果作为替换返回。99%的情况下,它似乎工作正常,但有时会发生冲突,因为gsub替换了不应该使用的东西 #!/bin/ksh rm $2 #Get rid of output file while read line; do #loop t

我有管道分隔的文本文件,它需要一个特定字段或一组字段的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
它将读取infle.txt、散列字段2、6和12,并写入outfile.txt。
非常感谢您的建议

使用
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“|”
    |
    定义为字段分隔符
  • -vo=“$old”
    -vn=“$new”
    让awk分别使用变量
    $old
    $new
    命名它们
  • {OFS=FS}
    -定义字段之间的分隔符。它也可以是
    OFS=“|”
    ,但这样我们指示
    awk
    使用我们在
    -F=“|”
    上定义的相同代码。在字段分隔符发生变化时,保留字段分隔符更为灵活
  • sub(o,n,$6)
    将变量
    o
    (即,
    $MYFIELD
    )上的文本替换为变量
    v
    (即,
    $MYHASH
    )上的文本,但仅在字段6上
  • 打印
    用替换文本打印整行
在您给出的评论示例中,这对我很有效:

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
希望能有帮助

编辑
我想要轻松地将变量传递给awk:
-vo=${variable\u name}

这样,解决方案可以是:

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

您是否尝试打印
sed
行以查看参数替换是否正确完成?有些想法像
echo“$line\| sed-e\”s/$MYFIELD/${MYHASH}/g“
@fedorqui这种替代品在大多数情况下似乎都很有效。当要散列的字段包含一组字符,这些字符与我不希望散列的另一个字段相匹配时,就会出现故障。例如,donthashit | foo1 | bar1 | foo2 | bar2 | hashit将按其应该的方式对字段6进行散列,但sed在第一个字段和最后一个字段中都看到了hashit,并将其替换。这是一个问题,因为我只希望它处理字段6。如果您指示
/g
,它将在每次找到它时更改它。你有什么模式来区分它们吗?我不确定我知道,除了我相信在大多数(也许所有?)情况下,冲突都会发生在第一个领域。因为第一个字段前面没有管道,所以我可以确保只替换以管道开头的字符串。这就是你要开车去的地方吗?经过一些测试,我想我用
awk
得到了它。请看下面的答案。这样我们就可以替换我们想要的字段(本例中为第6个)。很好,看起来很不错。你的解释特别有用。但是,分隔符不被保留;空格似乎已被替换。我会稍加修改的。你说得对,@Amw5G,我以前没见过。我刚刚编辑了我的答案以包含它的答案:我们需要使用
{OFS=FS}
来定义分隔符。现在它应该可以工作了。好极了@fedorqui,似乎可以。干杯
echo $line | awk -F"|" -v o=${MYFIELD} -v n=${MYHASH} '{OFS=FS} sub(o, n, $6) {print}' >> $2