我有两个长度相等的文件(即行号):
我想逐步将文件分成12个部分,当我迭代时,我需要在前10个部分中添加1个。
让我们说如果我的文件包含100行,我需要某种循环:
#!/bin/bash
F1=text.en
F2=text.cs
for i in `seq 0 9`;
do
split -n l/12 -d text.en
cat x10 > dev.en
cat x11 > test.en
echo "" > train.en
for j in `seq 0 $i`; do
cat x0$j >> train.en
done
split -n l/12 -d text.cs
cat x10 > dev.cs
cat x11 > test.cs
echo "" > train.cs
for j in `seq 0 $i`; do
cat x0$j >> train.cs
done
wc -l train.en train.cs
echo "############"
done
[OUT]:
55632 train.en
55468 train.cs
111100 total
############
110703 train.en
110632 train.cs
221335 total
############
165795 train.en
165011 train.cs
330806 total
############
它给了我文件之间不相等的块。
此外,当我使用split
时,它会分成不相等的块:
alvas@ubi:~/workspace/cvmt$ split -n l/12 -d text.en
alvas@ubi:~/workspace/cvmt$ wc -l x*
55631 x00
55071 x01
55092 x02
54350 x03
54570 x04
54114 x05
55061 x06
53432 x07
52685 x08
52443 x09
52074 x10
52082 x11
646605 total
我不知道没有。我手边的文件行,所以我不能使用split -l
选项。
如何将文件拆分为相等的大小。考虑到我之前不知道文件中有多少行?我应该使用wc -l
进行某种预先计算吗?
如何确保每个块中两个文件的分割大小相同?
(请注意,解决方案需要在行尾分割文件,即不要拆分任何行,只需逐行拆分文件。)
答案 0 :(得分:4)
您并不完全清楚自己想要实现的目标,但这里有几点建议:
split -n l/12
分成12个大小相等字节大小的块,而不是行数。
split -n r/12
将尝试均匀地分发行数,但如果块大小不是总行数的除数,那么你可以' ll仍会得到(稍微)不同的行数:额外行以循环方式分布。
例如,如果有100个输入行且行块大小为12,那么您的行数将为9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8
:100 / 12 = 8
(整数除法)和100 % 12 = 4
,所以所有文件至少 8
行,在前4个输出文件中分配额外的4行。
所以,是的,如果你想要所有文件的固定行数(除了最后一个,如果块大小不是除数),你必须预先计算总行数,执行整数除法以获得固定的行数,并使用split -l
计数:
totalLines=$(wc -l < text.en)
linesPerFile=$(( totalLines / 12 ))
split -l 12 text.en # with 100 lines, yields 8 files with 12 and 1 with 4 lines
补充意见:
使用小的固定迭代计数,使用大括号扩展(例如,for i in {0..9}
而非for i in `seq 0 9`
)更容易,更有效。
如果必须使用变量或使用更大的数字,请使用算术表达式:
n=9; for (( i = 0; i <= $n; i++ )); do ...; done
虽然您无法直接执行cat x0{0..$i}
(因为Bash在大括号扩展中不支持变量),但您可以通过合并seq -f
和xargs
来模拟它:
您可以替换
echo "" > train.en
for j in `seq 0 $i`; do
cat x0$j >> train.en
done
以下内容:
seq -f 'x%02.f' "$i" | xargs cat > train.en
由于您控制$i
的值,您甚至可以简化为:
eval "cat x0{0..$i}" > train.en # !! Only do this if you trust $i to contain a number.