我有以下测试文件:
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
谢谢!
答案 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
cut
和bc
来改善您的代码,并按照这样做
#!/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