天天看点

大了就要拆,拆完就要和。linux文件的分分合合:split,csplit

简介

本文将展示linux的split和csplit命令的几种使用场景。split和csplit命令可以用来在不同的场景拆分或者组合文件。

split只能通过文件大小拆分文件。csplit是split的扩展,可以通过匹配来拆分文件。匹配的方式可以为模式匹配、正则匹配以及字符串匹配。

示例

1 csplit使用正则匹配

使用csplit命令,可以通过正则匹配来分割文件。

命令格式:

csplit input_file '正则表达式' '{*}'
# input_file 待拆分的文件
# '{*}' 重复执行前面的表达式,直至结束
           

基础实例1

我们假设文件内容如下。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>
           

按照<dependency>进行切分,这样每个文件都是<dependency>...</dependency>。

示例:

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit test.xml '/^<dependency>$/' '{*}'
0
134
131
128
160
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 20
-rw-r--r-- 1 yunzhong yunzhong 553 Nov 27 10:34 test.xml
-rw-r--r-- 1 yunzhong yunzhong   0 Nov 27 14:25 xx00
-rw-r--r-- 1 yunzhong yunzhong 134 Nov 27 14:25 xx01
-rw-r--r-- 1 yunzhong yunzhong 131 Nov 27 14:25 xx02
-rw-r--r-- 1 yunzhong yunzhong 128 Nov 27 14:25 xx03
-rw-r--r-- 1 yunzhong yunzhong 160 Nov 27 14:25 xx04
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx00
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx01
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx00
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx02
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx03
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx04
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>

           

基础实例2

假设我们的文件内容如下:

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat functions
function main1 {
 echo "function main1"
}

function main2 {
 echo "function main2"
}

function main3 {
 echo "function main3"
}
           

我们需要将每个函数都拆分到单独的文件。如文件内容所示,每个函数的结束都是以大括号和换行。我们可以用这种方式来拆分函数。

命令格式如下:

csplit --elide-empty-files functions '/^}/+2' "{*}"
# /^}/+2 表示正则匹配字符“}”。找匹配后,向后推移两个字符。通过此方式来去掉空行。
# {*} 表示尽可能多的执行匹配。
           

执行结果:

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files functions '/^}/+2' "{*}"
43
43
43

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx00
function main1 {
 echo "function main1"
}

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx01
function main2 {
 echo "function main2"
}

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx02
function main3 {
 echo "function main3"
}

           

csplit模式匹配

类似于正则匹配,我们可以让csplit进行模式匹配。假设我们有文件。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat pattern
12345
asdfg
vbn
000
4634
fghvva
a000a
ceqdcad
433214
000

           

类似于正则匹配,我们通过“000”来拆分文件,且匹配后行+1.

执行命令:

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files  pattern '/000/+1' {*}
20
18
19
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx00
12345
asdfg
vbn
000
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx01
4634
fghvva
a000a
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx02
ceqdcad
433214
000
           

3 打印匹配内容

csplit可以打印匹配的内容,可以使用--suppress-matched参数强制输出匹配内容。ubuntu其实默认的就为打印,如上面的例子。

csplit --suppress-matched --elide-empty-files  pattern '/000/' {*}
16
12
15
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx00
12345
asdfg
vbn
           

打印结果说明:每个拆分文件的大小。可能和cat的内容不匹配。因为换行也是字符,但是不可见。

4 删除csplit 和 split产生的空文件

当使用csplit和split命令时,很有可能产生空文件。可以使用参数--elide-empty-files防止空文件产生。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat pattern
12345
asdfg
vbn
000
4634
fghvva
a000a
ceqdcad
433214
000
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit pattern '/000/+1' {*}
20
18
19
0
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$  csplit --elide-empty-files pattern '/000/+1' {*}
20
18
19
           

如上例子,当使用参数--elide-empty-files,输出的文件没有了“0”。

5 添加输出文件前缀

可以使用参数--prefix,为生成的文件添加前缀。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files --prefix subfile_  pattern '/000/' {*}
16
16
21
4
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 40
-rw-r--r-- 1 yunzhong yunzhong 129 Nov 27 20:56 functions
-rw-r--r-- 1 yunzhong yunzhong  57 Nov 27 21:06 pattern
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 20:59 subfile_00
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 20:59 subfile_01
-rw-r--r-- 1 yunzhong yunzhong  21 Nov 28 20:59 subfile_02
-rw-r--r-- 1 yunzhong yunzhong   4 Nov 28 20:59 subfile_03
           

6 通过多种匹配拆分文件

早期的版本,csplit通过匹配拆分文件,现在支持传入多个匹配值。例如,一篇文章有多个title,我们可以将多个title作为匹配值。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat multipattern
title1
content1
title2
content2
title3
content3
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files --prefix parts multipattern '/title1/' '/title2/' '/t
itle3/'
16
16
16
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 56
-rw-r--r-- 1 yunzhong yunzhong 129 Nov 27 20:56 functions
-rw-r--r-- 1 yunzhong yunzhong  48 Nov 28 21:01 multipattern
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:03 parts00
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:03 parts01
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:03 parts02
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat parts00
title1
content1
           

7 csplit生成文件设置后缀

默认情况下,csplit使用自定义语法创建拆分后的文件。你可以添加自定义前缀,也可以添加自定义后缀。

下面,我们为每个生成的文件设置后缀".data".

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files --prefix=subfile --suffix-format="%d.data"  pattern '
/000/' "{*}"
16
16
21
4
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 72
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:06 subfile0.data
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:06 subfile1.data
-rw-r--r-- 1 yunzhong yunzhong  21 Nov 28 21:06 subfile2.data
-rw-r--r-- 1 yunzhong yunzhong   4 Nov 28 21:06 subfile3.data
           

在命令中,我们使用了两个参数:

--prefix  => 在拆分后创建的所有文件的开始前添加前缀
--suffix  => 在拆分后创建的所有文件的末尾添加后缀
           

我们还可以指定文件的数字编码格式,下面的例子中编号采用两个数字:

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files --prefix=subfile --suffix-format="%02d.data" pattern '/000/' "{*}"
16
16
21
4
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 32
-rw-r--r-- 1 yunzhong yunzhong 129 Nov 27 20:56 functions
-rw-r--r-- 1 yunzhong yunzhong  48 Nov 28 21:01 multipattern
-rw-r--r-- 1 yunzhong yunzhong  57 Nov 27 21:06 pattern
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:09 subfile00.data
-rw-r--r-- 1 yunzhong yunzhong  16 Nov 28 21:09 subfile01.data
-rw-r--r-- 1 yunzhong yunzhong  21 Nov 28 21:09 subfile02.data
-rw-r--r-- 1 yunzhong yunzhong   4 Nov 28 21:09 subfile03.data
           

8 在模式匹配的基础上指定拆分个数

使用split命令,您可以将文件分割为特定的个数,但我们将在后面讨论。这里使用的是csplit命令,我们将基于模式匹配进行拆分,但我们还定义了在拆分文件中必须检查模式的次数。

下面的例子,虽然我们使用模式匹配拆分文件,但是不会重复拆分。因此只会拆分一次,分成两个文件。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat patterncount
#1 before first pattern
#2 before first pattern
pattern 000
#1 before second pattern
#2 before second pattern
pattern 000
#1 before third pattern
#2 before third pattern
pattern 000
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files --digits 1  patterncount '/000/+1' {0}
60
122
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xx1
#1 before second pattern
#2 before second pattern
pattern 000
#1 before third pattern
#2 before third pattern
pattern 000
           

其中:

{0} 标识不会重复匹配。因此在匹配一次后,不会再继续。如果设置成{1},那么只会重复一次,如下例。三个文件的内容长度分别为:60,6,60

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ csplit --elide-empty-files --digits 1  patterncount '/000/+1' {1}
60
62
60
           

9 通过行号来拆分文件

我们可以使用参数--lines来指定拆分的文件行数。最后一个文件的行数可能小于等于设定值。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat patterncount
#1 before first pattern
#2 before first pattern
pattern 000
#1 before second pattern
#2 before second pattern
pattern 000
#1 before third pattern
#2 before third pattern
pattern 000
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ split --lines 5 patterncount
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 28
-rw-r--r-- 1 yunzhong yunzhong 110 Nov 28 21:21 xaa
-rw-r--r-- 1 yunzhong yunzhong  72 Nov 28 21:21 xab
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xab
pattern 000
#1 before third pattern
#2 before third pattern
pattern 000
           

10 按照大小拆分文件

我们可以使用split按照文件的大小来拆分文件。

指定的文件大小可以用单位来标识:

K => KiloBytes
M => megaBytes
G => GigaBytes
           

代码示例:

split --bytes 1M my_file
           

11 split命令指定拆分后文件的后缀或扩展

和csplit类似,我们可以为split指定文件后缀,参数为:--additional-suffix

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ split --additional-suffix ".ext" -b 20 patterncount
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 60
-rw-r--r-- 1 yunzhong yunzhong 129 Nov 27 20:56 functions
-rw-r--r-- 1 yunzhong yunzhong  48 Nov 28 21:01 multipattern
-rw-r--r-- 1 yunzhong yunzhong  57 Nov 27 21:06 pattern
-rw-r--r-- 1 yunzhong yunzhong 182 Nov 28 21:13 patterncount
-rw-r--r-- 1 yunzhong yunzhong 553 Nov 27 10:34 test.xml
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xaa.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xab.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xac.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xad.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xae.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xaf.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xag.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xah.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:26 xai.ext
-rw-r--r-- 1 yunzhong yunzhong   2 Nov 28 21:26 xaj.ext
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xaa.ext
#1 before first patt
           

12 split命令拆分文件添加数字编号和后缀

参数--numeric-suffixes可以让split生成的文件带数字编码,且可以和参数--additional-suffix配合使用。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ split --numeric-suffixes --additional-suffix ".ext" -b 20 patterncount
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 60
-rw-r--r-- 1 yunzhong yunzhong 129 Nov 27 20:56 functions
-rw-r--r-- 1 yunzhong yunzhong  48 Nov 28 21:01 multipattern
-rw-r--r-- 1 yunzhong yunzhong  57 Nov 27 21:06 pattern
-rw-r--r-- 1 yunzhong yunzhong 182 Nov 28 21:13 patterncount
-rw-r--r-- 1 yunzhong yunzhong 553 Nov 27 10:34 test.xml
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x00.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x01.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x02.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x03.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x04.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x05.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x06.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x07.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:29 x08.ext
-rw-r--r-- 1 yunzhong yunzhong   2 Nov 28 21:29 x09.ext
           

13 split 增加前缀

和csplit类似,split可以添加前缀。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ split --numeric-suffixes --additional-suffix ".ext" -b 20 patterncount prefix_
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 60
-rw-r--r-- 1 yunzhong yunzhong 129 Nov 27 20:56 functions
-rw-r--r-- 1 yunzhong yunzhong  48 Nov 28 21:01 multipattern
-rw-r--r-- 1 yunzhong yunzhong  57 Nov 27 21:06 pattern
-rw-r--r-- 1 yunzhong yunzhong 182 Nov 28 21:13 patterncount
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_00.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_01.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_02.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_03.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_04.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_05.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_06.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_07.ext
-rw-r--r-- 1 yunzhong yunzhong  20 Nov 28 21:31 prefix_08.ext
-rw-r--r-- 1 yunzhong yunzhong   2 Nov 28 21:31 prefix_09.ext
           

14 split指定拆分个数

现在我们使用csplit将模式匹配后的文件拆分为特定的计数,而使用split我们不匹配模式,但我们可以定义拆分后创建的文件的计数。

可以通过参数--number设定拆分个数。

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ split --number 3 patterncount
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ ll
total 32
-rw-r--r-- 1 yunzhong yunzhong  60 Nov 28 21:33 xaa
-rw-r--r-- 1 yunzhong yunzhong  60 Nov 28 21:33 xab
-rw-r--r-- 1 yunzhong yunzhong  62 Nov 28 21:33 xac
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xaa
#1 before first pattern
#2 before first pattern
pattern 000
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xab
#1 before second pattern
#2 before second pattern
pattern 00yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xac
0
#1 before third pattern
#2 before third pattern
pattern 000
           

15 合并之前的拆分文件

我们可以将之前的拆分文件合并成一个,但不是使用csplit和split。

命令如下:

cat split-files-* > your_new_filename
           

示例:

yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat xa* > patterncountnew
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ cat patterncountnew
#1 before first pattern
#2 before first pattern
pattern 000
#1 before second pattern
#2 before second pattern
pattern 000
#1 before third pattern
#2 before third pattern
pattern 000
yunzhong@DESKTOP-9VB7LN7:/tmp/splitdir$ diff patterncount patterncountnew
           

通过diff可以看出,两个文件是完全一致的。

继续阅读