我想根据预定义的行集拆分文本文件。例如,我有一个文件
a
b
c
d
e
f
然后我有以下几组行(这些行可以存储在一个文件、多个文件中,这样更方便......)。
1,2
3,6
5,4
我想拆分我的文件以便得到 3 个文件,例如:
文件1
a
b
文件2
c
f
文件3
e
d
答案1
下面是一个bash
脚本,假设您的输入文件名为 infile,并且范围以每行 1 个的形式存储在名为 splits 的文件中:
i=1
for range in $(< splits); do
sed -n "$(echo "$range" | cut -f1 -d, )p" infile > "file$i"
sed -n "$(echo "$range" | cut -f2 -d, )p" infile >> "file$i"
((i++))
done
这仅用于sed
打印范围指定的行,并将每个结果保存为新文件(创建的文件名为 file1 file2 file3 等)。两次调用sed
用于保留行的指定顺序。
请注意,此简单脚本没有进行任何格式或错误检查,并且名为 file1 的现有文件将被覆盖。
简化的替代方案(由@muru)使用while read
并让 bash 分割范围而不是 cut:
i=1
while IFS=',' read n1 n2
do
sed -n "$n1 p; $n2 p" infile > "file$i"
((i++))
done < splits
如果输出文件中行的顺序很重要(例如行 5,4 != 4,5),那么该sed
位将需要分成两个类似于第一个脚本的单独调用。
答案2
下面的python脚本将进行拆分:
#!/usr/bin/python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file', type=argparse.FileType('r'))
parser.add_argument('lines', type=argparse.FileType('r'))
args = parser.parse_args()
file_lines = list(args.file)
for i, l in enumerate(args.lines):
r = l.rstrip().split(',')
with open('file{}'.format(i+1), 'w') as f:
for k in r:
try:
f.write(file_lines[int(k)-1])
except IndexError: # Ignore lines out of range
pass
简单地这样称呼:
./split.py file lines
<file>
abcdef 文件和1,2...... 行范围在哪里<lines>
(甚至可以有多行,如 1,6,3,18,5)
答案3
这是在 awk 中实现此目的的一种方法
awk -F, 'NR==FNR {for (i=1;i<=NF;i++) a[$i]=FNR; next;} {print $0 >> "outfile"a[FNR];}' index file
它读取索引文件,并将其行号 ( FNR
) 保存到由行上的值列表索引的数组中。然后它读取输入文件,并使用它是行号来查找什么输出要写入每行的文件编号。
答案4
另一种bash
解决方案,假设input
作为输入、pattern
作为模式和output
作为输出:
#!/bin/bash
i=0 # set the output number to 0
while read row; do # for each line in file `pattern` as $row
columns=$(<<< $row tr ',' '\n') # store each line obtained by transforming ',' in '\n' inside $row in an array $columns
for column in $columns; do # for each member in array $columns as $column
sed -n "${column}p" input
done > output$i # write column $column in `input` to `output$i`
((i++)) # increment the output number
done < pattern