如何在循环中使用awk命令生成多个精简数据文件

时间:2015-01-13 22:13:58

标签: bash loops awk

我有几个包含8列和120,000行的大型数据文件。现在我想从第100行开始每200行保留1行。我有脚本文件thin.sh:

awk '(NR%200==100)' original_file > thinned_file

但是,现在我有30个原始文件,这意味着我必须一点一点地修改命令30次,并且原始文件共享相似的名称:

data.0000.dat, data.0001.dat data.0002.dat, ..., data.0029.dat

我想必须有一些方法可以将awk命令嵌入到循环中以实现我的目标,可能是这样的:

for(i=0;i<30;i++);
do
    awk '(NR%200==100)' data.$i.dat > data.$i_thinned.dat
done

但我意识到文件名中00前面有$i的两位数字。我可以使用sprintf("%s")或其他什么吗?如果是,请如何安排awksprinf的订单? 我使用ubuntu和bash。

3 个答案:

答案 0 :(得分:3)

使用seq:

for i in $(seq -f %04g 1 29); do
  awk 'NR % 200 == 100' "data.${i}.dat" > "data.${i}_thinned.dat"
done

或者使用bash:

for i in {0001..0029}; do

引用在第一个片段中并不是绝对必要的,因为我们知道$i不包含任何邪恶的东西,但最好是对shell脚本中的扩展感到偏执。 "data.${i}_thinned.dat"中的大括号是必需的,因此shell不会查找要使用的变量$i_thinned。它们在"data.${i}.dat"中并不是绝对必要的,因为shell变量名称中不能包含.,但一致性很好。

答案 1 :(得分:0)

Ingedients(GAWK)

1 FNR - 当前档案中的记录号
1 match - 匹配正则表达式字符串,可以将组捕获到数组中 1 print - 打印以下数据(如果未提供,则默认为当前记录)
1 *.dat - 当前导演中以.dat结尾的所有文件。


说明

  1. 在条件块中检查当前文件中除以200时的当前记录号是否为剩余的100。
  2. 如果是,则运行下一个块{..}
  3. 获取当前文件名并匹配最后一个点,然后使用(.*)将所有内容捕获到数组a中。
  4. 使用带有扩展名a[1]
  5. 的捕获日期_thinned.dat打印到文件中
  6. 最后将*.dat添加到末尾以读取当前目录中的所有.dat文件

  7. 生成的代码

    gawk '(FNR%200==100){match(FILENAME,/(.*)\./,a);print >(a[1]"_thinned.dat")}' *.dat
    

答案 2 :(得分:0)

您只需要:

awk 'FNR==1{close(out); out=FILENAME; sub(/\.dat/,"_thinned&",out)} (FNR%200==100){print > out}' data.[0-9][0-9][0-9][0-9].dat

我使用data.[0-9][0-9][0-9][0-9].dat作为文件名通配模式而不是data.*.dat,以防您在先前生成所有&#34; _thinned&#34;的同一目录中重新运行脚本。文件。