我的测试数据
aa1
bb1
cc1
aa2
bb2
cc2
aa3
bb3
cc3
aa4
bb4
cc4
aa5
bb5
cc5
aa6
bb6
cc6
aa7
bb7
cc7
aa8
bb8
cc8
假设我希望将4-6行(aa2-cc2)提取到文件中,然后跳过6行并提取行13-15(aa5-cc5),然后跳过6行。该过程将重复直到文件结束。我写了一个bash脚本,适用于小文件。
#!/bin/bash
for i in {2..8..3}; do
sed -n "$((3*i-2))","$((3*i))"p testdata > "$i".part
done
现在我正在处理一个30 GB的巨型文件,我的脚本对于硬盘是不好的,因为它将读取相同的文件数千次。我希望通过只读取(并提取我的部分)文件一次来避免硬盘损坏。是否有可以解决我的问题的单线程?
我不是一个真正的程序员,所以请在我的问题中混淆任何术语混淆。谢谢你的帮助!
答案 0 :(得分:3)
只需单次传递文件即可。加上一点算术。
display: flex;
justify-content: center;
align-items:center
答案 1 :(得分:3)
在GNU sed
中,可以使用first~step
line addressing:
sed -n '4~9p; 5~9p; 6~9p' file
答案 2 :(得分:3)
你可以在sed中进行循环,例如与GNU sed:
# Skip first 3 lines, extract 3 lines and skip 6
sed -n '4~9 { N; N; p }'
使用示例:
seq 40 | sed -n '4~9 { N; N; p }'
输出:
4
5
6
13
14
15
22
23
24
31
32
33
请注意,此解决方案仅打印整个文本块。如果最后一个块中没有足够的行,则不会打印它,即上例中的40,41,42
。
4~9
告诉sed,从第4行开始,每9行只执行一次代码块{ N; N; p }
因此,对于每9行,我们再获取2行(N; N
),然后将它们全部打印p
答案 3 :(得分:1)
IIUC,您想要提取行并写入某个文件,如果是这样,如果您可以再创建一个文件来提取带有范围的记录列表,那么您可以尝试下面的一个,
假设您有一个名为extract
的文件,其中包含您感兴趣的范围
$ cat extract
4-6
13-15
这是您的输入文件
$ cat file
aa1
bb1
cc1
aa2
bb2
cc2
aa3
bb3
cc3
aa4
bb4
cc4
aa5
bb5
cc5
aa6
bb6
cc6
aa7
bb7
cc7
aa8
bb8
cc8
如果执行如下:
$ awk -F'[- ]' 'FNR==NR{rules[FNR,"min"]=$1;rules[FNR,"max"]=$2;m=FNR;next}function is_in_list(i){for(i=1; i <=m; i++)if(FNR>=rules[i,"min"] && FNR<=rules[i,"max"])return rules[i,"min"]"-"rules[i,"max"]".txt"}{file=is_in_list()}file{ if(file in arr){ print >>file }else{ print >file; arr[file] } close(file) }' extract file
你得到:
$ ls *.txt
13-15.txt 4-6.txt
每个文件的内容如下:
$ cat 4-6.txt
aa2
bb2
cc2
$ cat 13-15.txt
aa5
bb5
cc5
如果您只想列出行
$ awk -F'[- ]' 'FNR==NR{rules[FNR,"min"]=$1;rules[FNR,"max"]=$2;m=FNR;next}function is_in_list(i){for(i=1; i <=m; i++)if(FNR>=rules[i,"min"] && FNR<=rules[i,"max"])return rules[i,"min"]"-"rules[i,"max"]".txt"}is_in_list()' extract file
aa2
bb2
cc2
aa5
bb5
cc5
写入单个文件的更好的可读性:
awk -F'[- ]' '
FNR==NR{
rules[FNR,"min"]=$1;
rules[FNR,"max"]=$2;
m=FNR;
next
}
function is_in_list(i)
{
for(i=1; i <=m; i++)
if(FNR>=rules[i,"min"] && FNR<=rules[i,"max"])
return rules[i,"min"]"-"rules[i,"max"]".txt"
}
{
file=is_in_list()
}
file{
if(file in arr){
print >>file
}
else{
print >file;
arr[file]
}
close(file)
}
' extract file
对于给定范围
,列表行更易于阅读awk -F'[- ]' '
FNR==NR{
rules[FNR,"min"]=$1;
rules[FNR,"max"]=$2;
m=FNR;
next
}
function is_in_list(i)
{
for(i=1; i <=m; i++)
if(FNR>=rules[i,"min"] && FNR<=rules[i,"max"])
return rules[i,"min"]"-"rules[i,"max"]".txt"
}
is_in_list()
' extract file
答案 4 :(得分:0)
关注awk也可以帮助你。
awk '
function jump(var){
while(var>0){
getline;
var--
}}
FNR==4{
val++
}
val>=1&&val<=3{
print $0;
val++
}
val==4{
jump(val+2);
val=1
}
' Input_file
输出如下。
aa2
bb2
cc2
aa5
bb5
cc5
aa8
bb8
cc8