我在上一篇文章中使用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个数字的窗口,而不仅仅是行。
答案 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
显然,这将比awk快,并且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
我使用较小的t
和d
值对其进行了测试,但它似乎按要求运行。
最后一句话:对于大输入文件,我不鼓励将整个内容存储在数组a
中。