在awk中插入if循环

时间:2014-02-14 17:37:51

标签: bash if-statement awk

我在上一篇文章中使用awk解决了一个问题,但现在我想在其中添加一个if循环,但是我收到了错误。

问题在于:

我有很多看起来像这样的文件:

 Header
 175566717.000
 175570730.000
 175590376.000
 175591966.000
 175608932.000
 175612924.000
 175614836.000
 .
 .
 .
 175680016.000
 175689679.000
 175695803.000
 175696330.000

我想提取前2000行(第1行到第2000行),然后将行提取1500到3500,然后提取3000到5000等等......我的意思是:提取一个2000行的窗口在连续窗口之间重叠500行,直到文件结束。

这是用于它的awk命令:

awk -v i=1 -v t=2000 -v d=501 'NR>1{a[NR-1]=$0}END{
    while(i<NR-1){
        ++n;
        for(k=i;k<i+t;k++)print a[k] > "win"n".txt"; 
        close("_win"n".txt") 
        i=i+t-d
    }

}' myfile.txt
done

我得到几个名字为win1.txt,win2.txt,win3.txt等的文件......

我现在的问题是因为文件不是2000的倍数,我的最后一个窗口少于2000行。如何设置一个if循环来执行此操作:如果最后一个窗口的数字编号小于2000,则前一个窗口应该包含所有行,直到文件结尾。

额外信息

当创建窗口时,最后会有一个换行符。这就是为什么我需要if循环来考虑一个少于2000个数字的窗口,而不仅仅是行。

2 个答案:

答案 0 :(得分:1)

如果您出于其他原因不必使用,请尝试使用方法

#!/bin/bash
file="$(sed '/^\s*$/d' myfile.txt)"
sed -n 1,2000p <<< "$file"
first=1500
last=3500
max=$(wc -l <<< "$file" | awk '{print $1}')
while [[ $max -ge 2000 && $last -lt $((max+1500)) ]]; do
  sed -n "$first","$last"p <<< "$file"
  ((first+=1500))
  ((last+=1500))
done

显然,这将比快,并且gigatic文件更容易出错,但在大多数情况下都应该有效。

答案 1 :(得分:1)

更改while条件以使其提前停止:

while (i+t <= NR) {

更改for循环的结束条件以补偿最后一个可能更大的输出文件:

for (k = i; k < (i+t+t-d <= NR ? i+t : NR); k++)

其余代码可以保持不变;虽然我冒昧地删除close语句(为什么会这样?),并设置d=500,以使输出文件真正重叠500行。

awk -v i=1 -v t=2000 -v d=500 'NR>1{a[NR-1]=$0}END{
    while (i+t <= NR) {
        ++n;
        for (k=i; k < (i+t+t-d <= NR ? i+t : NR); k++) print a[k] > "win"n".txt"; 
        i=i+t-d
    }
}' myfile.txt

我使用较小的td值对其进行了测试,但它似乎按要求运行。

最后一句话:对于大输入文件,我不鼓励将整个内容存储在数组a中。