98

-|在每个部分之后都有一个带有分隔符的文件...需要使用 unix 为每个部分创建单独的文件。

输入文件示例

wertretr
ewretrtret
1212132323
000232
-|
ereteertetet
232434234
erewesdfsfsfs
0234342343
-|
jdhg3875jdfsgfd
sjdhfdbfjds
347674657435
-|

文件 1 中的预期结果

wertretr
ewretrtret
1212132323
000232
-|

文件 2 中的预期结果

ereteertetet
232434234
erewesdfsfsfs
0234342343
-|

文件 3 中的预期结果

jdhg3875jdfsgfd
sjdhfdbfjds
347674657435
-|
4

11 回答 11

105

一个班轮,没有编程。(除了正则表达式等)

csplit --digits=2  --quiet --prefix=outfile infile "/-|/+1" "{*}"

测试: csplit (GNU coreutils) 8.30

Apple Mac 上的使用注意事项

“对于 OS X 用户,请注意csplit操作系统附带的版本不起作用。您需要 coreutils 中的版本(可通过 Homebrew 安装),称为gcsplit.” — @Danial

“只是补充一点,您可以获得适用于 OS X 的版本(至少与 High Sierra 一起使用)。您只需要稍微调整一下参数csplit -k -f=outfile infile "/-\|/+1" "{3}"。似乎不起作用的功能是"{*}",我必须具体说明" -k_ --digits_ -n_ — @Pebbl

于 2012-07-03T16:07:14.033 回答
43
awk '{f="file" NR; print $0 " -|"> f}' RS='-\\|'  input-file

解释(编辑):

RS是记录分隔符,此解决方案使用 gnu awk 扩展,允许它包含多个字符。NR是记录号。

print 语句将一条记录打印" -|"到一个文件中,该文件的名称中包含记录号。

于 2012-07-03T16:04:39.550 回答
7

Debian 有csplit,但我不知道这是否对所有/大多数/其他发行版都通用。如果不是,那么追踪源代码并编译它应该不会太难......

于 2012-07-03T15:42:42.810 回答
5

我解决了一个稍微不同的问题,其中文件包含一行名称,后面的文本应该放在哪里。这个 perl 代码对我有用:

#!/path/to/perl -w

#comment the line below for UNIX systems
use Win32::Clipboard;

# Get command line flags

#print ($#ARGV, "\n");
if($#ARGV == 0) {
    print STDERR "usage: ncsplit.pl --mff -- filename.txt [...] \n\nNote that no space is allowed between the '--' and the related parameter.\n\nThe mff is found on a line followed by a filename.  All of the contents of filename.txt are written to that file until another mff is found.\n";
    exit;
}

# this package sets the ARGV count variable to -1;

use Getopt::Long;
my $mff = "";
GetOptions('mff' => \$mff);

# set a default $mff variable
if ($mff eq "") {$mff = "-#-"};
print ("using file switch=", $mff, "\n\n");

while($_ = shift @ARGV) {
    if(-f "$_") {
    push @filelist, $_;
    } 
}

# Could be more than one file name on the command line, 
# but this version throws away the subsequent ones.

$readfile = $filelist[0];

open SOURCEFILE, "<$readfile" or die "File not found...\n\n";
#print SOURCEFILE;

while (<SOURCEFILE>) {
  /^$mff (.*$)/o;
    $outname = $1;
#   print $outname;
#   print "right is: $1 \n";

if (/^$mff /) {

    open OUTFILE, ">$outname" ;
    print "opened $outname\n";
    }
    else {print OUTFILE "$_"};
  }
于 2012-12-01T00:27:02.377 回答
4

以下命令对我有用。希望能帮助到你。

awk 'BEGIN{file = 0; filename = "output_" file ".txt"}
    /-|/ {getline; file ++; filename = "output_" file ".txt"}
    {print $0 > filename}' input
于 2017-02-07T19:40:56.473 回答
3

您也可以使用 awk。我对 awk 不是很熟悉,但以下内容似乎对我有用。它生成了 part1.txt、part2.txt、part3.txt 和 part4.txt。请注意,生成的最后一个 partn.txt 文件是空的。我不知道如何解决这个问题,但我相信它可以通过一些调整来完成。有什么建议吗?

awk_pattern 文件:

BEGIN{ fn = "part1.txt"; n = 1 }
{
   print > fn
   if (substr($0,1,2) == "-|") {
       close (fn)
       n++
       fn = "part" n ".txt"
   }
}

bash 命令:

awk -f awk_pattern input.file

于 2012-07-03T16:00:01.680 回答
2

csplit有的话就用。

如果你没有,但你有 Python……不要使用 Perl。

懒惰读取文件

您的文件可能太大而无法一次全部保存在内存中 - 逐行阅读可能更可取。假设输入文件名为“samplein”:

$ python3 -c "from itertools import count
with open('samplein') as file:
    for i in count():
        firstline = next(file, None)
        if firstline is None:
            break
        with open(f'out{i}', 'w') as out:
            out.write(firstline)
            for line in file:
                out.write(line)
                if line == '-|\n':
                    break"
于 2017-10-24T20:10:56.437 回答
2

这是一个 Python 3 脚本,它根据分隔符提供的文件名将文件拆分为多个文件。示例输入文件:

# Ignored

######## FILTER BEGIN foo.conf
This goes in foo.conf.
######## FILTER END

# Ignored

######## FILTER BEGIN bar.conf
This goes in bar.conf.
######## FILTER END

这是脚本:

#!/usr/bin/env python3

import os
import argparse

# global settings
start_delimiter = '######## FILTER BEGIN'
end_delimiter = '######## FILTER END'

# parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input-file", required=True, help="input filename")
parser.add_argument("-o", "--output-dir", required=True, help="output directory")

args = parser.parse_args()

# read the input file
with open(args.input_file, 'r') as input_file:
    input_data = input_file.read()

# iterate through the input data by line
input_lines = input_data.splitlines()
while input_lines:
    # discard lines until the next start delimiter
    while input_lines and not input_lines[0].startswith(start_delimiter):
        input_lines.pop(0)

    # corner case: no delimiter found and no more lines left
    if not input_lines:
        break

    # extract the output filename from the start delimiter
    output_filename = input_lines.pop(0).replace(start_delimiter, "").strip()
    output_path = os.path.join(args.output_dir, output_filename)

    # open the output file
    print("extracting file: {0}".format(output_path))
    with open(output_path, 'w') as output_file:
        # while we have lines left and they don't match the end delimiter
        while input_lines and not input_lines[0].startswith(end_delimiter):
            output_file.write("{0}\n".format(input_lines.pop(0)))

        # remove end delimiter if present
        if not input_lines:
            input_lines.pop(0)

最后是你如何运行它:

$ python3 script.py -i input-file.txt -o ./output-folder/
于 2017-02-19T19:33:57.303 回答
1
cat file| ( I=0; echo -n "">file0; while read line; do echo $line >> file$I; if [ "$line" == '-|' ]; then I=$[I+1]; echo -n "" > file$I; fi; done )

和格式化版本:

#!/bin/bash
cat FILE | (
  I=0;
  echo -n"">file0;
  while read line; 
  do
    echo $line >> file$I;
    if [ "$line" == '-|' ];
    then I=$[I+1];
      echo -n "" > file$I;
    fi;
  done;
)
于 2012-07-03T15:49:01.670 回答
0

这是一个 perl 代码,它将做这件事

#!/usr/bin/perl
open(FI,"file.txt") or die "Input file not found";
$cur=0;
open(FO,">res.$cur.txt") or die "Cannot open output file $cur";
while(<FI>)
{
    print FO $_;
    if(/^-\|/)
    {
        close(FO);
        $cur++;
        open(FO,">res.$cur.txt") or die "Cannot open output file $cur"
    }
}
close(FO);
于 2012-07-03T16:00:50.963 回答
0

这是我为以下问题编写的上下文拆分问题: http ://stromberg.dnsalias.org/~strombrg/context-split.html

$ ./context-split -h
usage:
./context-split [-s separator] [-n name] [-z length]
        -s specifies what regex should separate output files
        -n specifies how output files are named (default: numeric
        -z specifies how long numbered filenames (if any) should be
        -i include line containing separator in output files
        operations are always performed on stdin
于 2012-07-03T17:17:59.197 回答