如何拆分文件并保留每个部分的第一行?

Ark*_*ady 58 linux bash shell text file

给定:一个具有"特殊"第一行的大文本数据文件(例如CSV格式)(例如,字段名称).

通缉:相当于coreutils split -l命令,但附加要求原始文件中的标题行出现在每个结果片段的开头.

我猜一些混合物split并且head会做的伎俩?

Pau*_*ce. 49

这是robhruska的脚本清理了一下:

tail -n +2 file.txt | split -l 4 - split_
for file in split_*
do
    head -n 1 file.txt > tmp_file
    cat "$file" >> tmp_file
    mv -f tmp_file "$file"
done
Run Code Online (Sandbox Code Playgroud)

我删除wc,cut,ls以及echo在他们不必要的地方.我改变了一些文件名,使它们更有意义.我把它分成多行只是为了让它更容易阅读.

如果你想获得花哨,你可以使用mktemptempfile创建一个临时文件名,而不是使用硬编码文件.

编辑

使用GNU split可以这样做:

split_filter () { { head -n 1 file.txt; cat; } > "$FILE"; }; export -f split_filter; tail -n +2 file.txt | split --lines=4 --filter=split_filter - split_
Run Code Online (Sandbox Code Playgroud)

因可读性而破裂:

split_filter () { { head -n 1 file.txt; cat; } > "$FILE"; }
export -f split_filter
tail -n +2 file.txt | split --lines=4 --filter=split_filter - split_
Run Code Online (Sandbox Code Playgroud)

--filter指定时,split运行用于每个输出文件的命令(在此情况下的函数,其必须导出)并设置变量FILE,在命令的环境,到文件名.

过滤器脚本或函数可以对输出内容甚至文件名进行任何操作.后者的一个例子可能是输出到变量目录中的固定文件名:> "$FILE/data.dat"例如.


Tim*_*son 19

这个单行将大 csv 拆分为 999 条记录,保留每个记录顶部的标题行(因此 999 条记录 + 1 个标题 = 1000 行)

cat bigFile.csv | parallel --header : --pipe -N999 'cat >file_{#}.csv'
Run Code Online (Sandbox Code Playgroud)

基于 Ole Tange 的回答。(重新 Ole 的回答:您不能将行数与 pipepart 一起使用)

有关安装并行的一些提示,请参阅评论

  • 与 MacOS 一样,Ubuntu 20.04 也需要安装“parallel”才能正常工作。请注意,Ubuntu 建议使用 `sudo apt install moreutils` _# version 0.63-1_ 或 `sudo apt install parallel` _# version 20161222-1.1_ - 请选择后一个建议。第一个建议“moreutils”听起来特别有用,但是该包中包含的并行版本出错了(“并行:无效选项 - '-'”)。第二个建议按预期工作([详细信息](/sf/answers/1365237121/))。 (3认同)
  • 我必须在 macOS 上“brew install parallel”。奇迹般有效! (2认同)

pix*_*eat 13

您可以在GNU coreutils split> = 8.13(2011)中使用新的--filter功能:

tail -n +2 FILE.in |
split -l 50 - --filter='sh -c "{ head -n1 FILE.in; cat; } > $FILE"'
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢单线版.为了让bash更通用,我做了:`tail -n +2 FILE.in | split -d --lines 50 - --filter ='bash -c"{head -n1 $ {FILE%.*}; cat;}> $ FILE"'FILE.in.x` (2认同)

mar*_*rco 10

你可以使用[mg] awk:

awk 'NR==1{
        header=$0; 
        count=1; 
        print header > "x_" count; 
        next 
     } 

     !( (NR-1) % 100){
        count++; 
        print header > "x_" count;
     } 
     {
        print $0 > "x_" count
     }' file
Run Code Online (Sandbox Code Playgroud)

100是每个切片的行数.它不需要临时文件,可以放在一行.


Rob*_*ska 7

关于Bash-fu,我是新手,但我能够炮制出这两个命令的怪物。我敢肯定还有更优雅的解决方案。

$> tail -n +2 file.txt | split -l 4
$> for file in `ls xa*`; do echo "`head -1 file.txt`" > tmp; cat $file >> tmp; mv -f tmp $file; done
Run Code Online (Sandbox Code Playgroud)

这是假设您的输入文件是file.txt,您没有使用的prefix参数split,并且您正在的目录中没有其他任何以split的默认xa*输出格式开头的文件。另外,将“ 4”替换为所需的分割线尺寸。