unix下将大文件分割成多个文件

unix下将大文件分割成多个文件

我有一个包含多行(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-asplit将命名类似 的文件new_file00new_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

相关内容