根据行号将一个文件分成不同的文件

时间:2017-05-05 12:15:51

标签: bash awk

我有以下测试文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

我想以每个文件包含前一个文件的最后一行作为第一行的方式将其分开。例子是:

file 1:
1
2
3
4
5
file2: 
5
6
7
8
9
file3:
9
10
11
12
13
file4:
13
14
15
16
17
file5:
17
18
19
20

这将产生4行5行和1行4行。

作为第一步,我尝试测试我编写的以下命令,只获取包含前5行的第一个文件。我无法弄清楚awk语句中if命令的原因,而不是打印前5行,而是打印整个20行?

d=$(wc test)
a=$(echo $d | cut -f1 -d " ")
lines=$(echo $a/5 | bc -l)
integer=$(echo $lines | cut -f1 -d ".")
for i in $(seq 1 $integer); do
start=$(echo $i*5 | bc -l)
var=$((var+=1))
echo start $start
echo $var
if [[ $var = 1 ]]; then
    awk 'NR<=$start' test
fi
done

谢谢!

4 个答案:

答案 0 :(得分:3)

为什么不使用split工具包中提供的POSIX util。它可以选择拆分行数,您可以将其作为5

split -l 5 input-file

man split页面

-l, --lines=NUMBER
       put NUMBER lines/records per output file

请注意,-l也是POSIX compliant

答案 1 :(得分:2)

$ ls
$
$ seq 20 | awk 'NR%4==1{ if (out) { print > out; close(out) } out="file"++c } {print > out}'
$
$ ls
file1  file2  file3  file4  file5

$ cat file1
1
2
3
4
5
$ cat file2
5
6
7
8
9
$ cat file3
9
10
11
12
13
$ cat file4
13
14
15
16
17
$ cat file5
17
18
19
20

如果您曾试图使用shell循环再次操作文本,请务必首先阅读https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice以了解至少使用awk的一些原因。要学习awk,请阅读Arnold Robbins撰写的Effective Awk Programming,第4版。

哦。以及为什么你的awk命令awk 'NR<=$start' test不起作用 - awk不是shell,它没有比C程序更多的shell变量访问权限(反之亦然)。要使用名为awkstart的shell变量的值初始化名为start的awk变量,然后在脚本中使用该awk变量,您需要awk -v awkstart="$start" 'NR<=awkstart' test。 awk变量也可以命名为start或其他任何合理的 - 它与shell变量的名称完全无关。

答案 2 :(得分:0)

您可以删除不必要的echo cutbc来改善您的代码,并按照这样做

#!/bin/bash
for i in $(seq $(wc -l < test) ); do
    (( i % 4 != 1 )) && continue
    tail +$i test | head -5 > "file$(( 1+i/4 ))"
done

但是awk解决方案仍然好得多。只读一次文件并根据随时可用的信息(如亚麻布)采取行动是可行的方法。在shell 必须计算行数,没有办法绕过它。 awk会免费提供(以及许多其他内容)。

答案 3 :(得分:0)

使用split

$ seq 20 | split -l 5
$ for fn in x*; do echo "$fn"; cat "$fn"; done
xaa
1
2
3
4
5
xab
6
7
8
9
10
xac
11
12
13
14
15
xad
16
17
18
19
20

或者,如果你有一个文件:

$ split -l test_file