awk如何操纵两文件?

sh/bash/dash/ksh/zsh等Shell脚本
回复
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

awk如何操纵两文件?

#1

帖子 谢宝良 » 2016-04-10 21:12

问题:朋友在一小厂做核算员,工厂有30多工种,数百每个工人,每个工人每天做的工种会变化,每天要计算出每个工人的工种对应的数量,当天的工资。

假设a,b,c······表示工种,第二行表示对应工种单位量的报酬。
文件1:
a c d e f g h
0.5 0.8 1.1 0.5 1.0 0.8 0.7


文件2说明:
30表示当天完成a工种的数量,乘以文件1的单位报酬0.5,即得该工种的总报酬。加上其余两项的报酬就是当天李四的工资。
文件2:

李四 a:30 c:150 f:70
张三 d:60 f:20 g:4
陈明 a:50 d:30 e:50


因为我只懂libreoffice的宏,而且朋友单位的office宏中毒了,所以想用awk for win
来处理这些数据。
那位熟悉awk操纵两文件的方法,帮帮忙。
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#2

帖子 谢宝良 » 2016-04-10 21:55

awk 'NR==FNR{a[$1]=$2}NR>FNR{for(i=2;i<=NF;i++){split($i,b,":") m=m+a[b[1]])*b[2] print $1,m}}' file1 file2 >file3

这个命令出现好多错误。
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#3

帖子 谢宝良 » 2016-04-10 21:59

awk 'NR==FNR{a[$1]=$2}NR>FNR{for(i=2;i<=NF;i++){split($i,b,":");m=m+a[b[1]]*b[2]; print $1,m}}' file2 file1 >file3


看看如何。

错了,应该是第一行是下标,第二行是值。
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#4

帖子 谢宝良 » 2016-04-10 22:20

最丑陋的方法:
awk 'NR==1{for(i=1;i<=NF;i++){a=$i}} NR==2{for(i=1;i<=NF;i++){aa[a]=$i}} NR>FNR{for(i=2;i<=NF;i++){split($i,b,":");m=m+aa[b[1]]*b[2]; print $1,m}}' 1 2


m会一直积累下来。不行。
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#5

帖子 谢宝良 » 2016-04-10 22:34

awk 'NR==1{for(i=1;i<=NF;i++){a=$i}} NR==2{for(i=1;i<=NF;i++){aa[a]=$i}} NR>FNR{for(i=2;i<=NF;i++){split($i,b,":");m=m+aa[b[1]]*b[2]} print $1,m}' 1 2
勉强可以了
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#6

帖子 谢宝良 » 2016-04-10 22:37

因为涉及到钱,所以还是请高手帮忙完善一下。怎么写更严密点。
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#7

帖子 谢宝良 » 2016-04-10 22:48

果然,还有漏洞,


awk 'NR==1{for(i=1;i<=NF;i++){a=$i}} NR==2{for(i=1;i<=NF;i++){aa[a]=$i}} NR>FNR{for(i=2;i<=NF;i++){split($i,b,":");m=m+aa[b[1]]*b[2]} print $1,m;m=0}' 1 2

每次算完一个工人,工资m必须初始为0.
头像
Arthur2e5
帖子: 7
注册时间: 2015-11-30 6:11
系统: Windows 10b14295

Re: awk如何操纵两文件?

#8

帖子 Arthur2e5 » 2016-04-11 4:07

有 msys2 的话可以用 bash 4.x 啊:

代码: 全选

#!/bin/bash

exec 3<file_1
read -r -u 3 -a work
read -r -u 3 -a price

declare -A money_per_h
for ((i=0; i<${#work[@]}; i++)); do
  money_per_h["${work[i]}"]=${price[i]}
done
exec 3<&-

exec 4<file_2
while read -r -u 4 name work; do
  money=0
  read -ra work <<< "$work"
  for i in "${work[@]}"; do
    IFS=':' read -r worktype time _trash <<< "$i"
    ((money += "${money_per_h["$worktype"]}" * time))
  done
  echo "$name: $money"
done
msys 的 bash 3.1 也不是不可以,但是模拟关系数组写起来头疼(

顺便一提,LibreOffice Basic 和 MS Office VBA 几乎是一样的……
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#9

帖子 谢宝良 » 2016-04-11 9:24

Arthur2e5 写了:有 msys2 的话可以用 bash 4.x 啊:

代码: 全选

#!/bin/bash

exec 3<file_1
read -r -u 3 -a work
read -r -u 3 -a price

declare -A money_per_h
for ((i=0; i<${#work[@]}; i++)); do
  money_per_h["${work[i]}"]=${price[i]}
done
exec 3<&-

exec 4<file_2
while read -r -u 4 name work; do
  money=0
  read -ra work <<< "$work"
  for i in "${work[@]}"; do
    IFS=':' read -r worktype time _trash <<< "$i"
    ((money += "${money_per_h["$worktype"]}" * time))
  done
  echo "$name: $money"
done
msys 的 bash 3.1 也不是不可以,但是模拟关系数组写起来头疼(

顺便一提,LibreOffice Basic 和 MS Office VBA 几乎是一样的……
多谢帮忙,感觉还是使用awk for win更方便,免安装,放进c盘就能用。

而且awk更容易理解和修改,想要怎么处理数据都行。
谢宝良
帖子: 1983
注册时间: 2010-05-01 21:23

Re: awk如何操纵两文件?

#10

帖子 谢宝良 » 2016-04-12 10:00

感觉awk操纵excel还是不方便,不知python能在u盘免安装运行吗?
回复