我有一个包含多行(9074 行)的文件,我想将该文件拆分为 10 个包含相同行数的文件,除了包含剩余行数的最后一个文件
split -l `wc -l myfile | awk '{print $1/10}'` myfile
split: invalid number of lines: ‘907.4’
我希望最后一个文件包含 907+4 行
答案1
你必须做整数-l
除法得到的参数值split
。 shell 非常适合整数除法:
lines_number=$(wc -l < file)
split -l $((lines_number / 10)) file
wc -l x*
907 xaa
907 xab
907 xac
907 xad
907 xae
907 xaf
907 xag
907 xah
907 xai
907 xaj
4 xak
9074 total
如果你想用awk
它,你必须打印一个整数:
wc -l file | awk '{print int($1/10)}'
907
您必须连接最后两个文件。假设您将它们全部输出到同一个空目录中,您可以执行以下操作:
printf "%s\n" x* | tail -n2 | xargs cat > last_file
wc -l < last_file
911
在上面,我们知道 glob 匹配将按字母顺序获取新文件,并且我们知道 split 会按照该顺序命名输出文件。
注意:我还喜欢对 的输出文件使用自定义前缀和数字索引split
,如下所示:
split -d -l 907 file new_file
注意:由于后缀长度默认为 2,(请参阅man split
和-a
)split
将命名类似 的文件new_file00
,new_file01
只要它们小于 100(3 位后缀长度),就会再次按字母顺序排序。同时具有数字后缀(为了人类可读性)和字母顺序的另一个选项是将后缀长度设置-a
为适当的值。
要将整个过程包含在一个小脚本中,您可以这样做。我还添加了对模数是否为零的检查,在这种情况下我们不会修改任何输出文件。
#!/bin/bash
f="file"
prefix="new_file"
lines_number=$(wc -l < "$f")
split -d -l $((lines_number / 10)) "$f" "$prefix"
if ((lines_number % 10 != 0)); then
last_file=$(printf "%s\n" "$prefix"* | tail -1)
pre_last_file=$(printf "%s\n" "$prefix"* | tail -2 | head -1)
cat "$last_file" >> "$pre_last_file" && rm -- "$last_file"
fi