Як розділити великий текстовий файл на менші файли з однаковою кількістю рядків?


515

У мене є великий (за кількістю рядків) звичайний текстовий файл, який я хотів би розділити на менші файли, також за кількістю рядків. Отже, якщо мій файл має близько 2М рядків, я б хотів розділити його на 10 файлів, що містять 200k рядків, або 100 файлів, що містять 20k рядків (плюс один файл із залишком; бути рівномірним поділом не має значення).

Я міг би зробити це досить легко в Python, але мені цікаво, чи існує який-небудь спосіб ніндзя зробити це за допомогою утилітів bash та unix (на відміну від ручного циклу числення та підрахунку / розподілу ліній).


2
З цікавості, після того, як вони "розкололися", як їх "поєднувати"? Щось на кшталт "котяча частина2 >> частина1"? Або є ще одна утиліта ніндзя? проти оновлення запитання?
dlamotte

7
Щоб повернути це разом,cat part* > original
Марк Байєрс

9
так, кіт короткий для приєднання. Загалом, апріпос корисний для пошуку відповідних команд. IE бачити вихід: apropos split
pixelbeat

@pixelbeat Це дуже круто, дякую
danben

3
Окрім цього, користувачі OS X повинні переконатися, що їх файл містить переключення рядків / індикатори кінцевих рядків у стилі LINUX або UNIX (LF) замість MAC OS X - індикатори кінцевих рядків у стилі (CR) - розділення та Команди csplit не працюватимуть, якщо ваші подібні перерви - це повернення перевезення замість LineFeeds. TextWrangler від програмного забезпечення BareBones може допомогти вам у цьому, якщо ви працюєте на Mac OS. Ви можете вибрати, як виглядатимуть символи розриву рядків. під час збереження (або збереження як ...) своїх текстових файлів.

Відповіді:


856

Ви подивилися на команду розділення?

$ split --help
Usage: split [OPTION] [INPUT [PREFIX]]
Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default
size is 1000 lines, and default PREFIX is `x'.  With no INPUT, or when INPUT
is -, read standard input.

Mandatory arguments to long options are mandatory for short options too.
  -a, --suffix-length=N   use suffixes of length N (default 2)
  -b, --bytes=SIZE        put SIZE bytes per output file
  -C, --line-bytes=SIZE   put at most SIZE bytes of lines per output file
  -d, --numeric-suffixes  use numeric suffixes instead of alphabetic
  -l, --lines=NUMBER      put NUMBER lines per output file
      --verbose           print a diagnostic to standard error just
                            before each output file is opened
      --help     display this help and exit
      --version  output version information and exit

Ви можете зробити щось подібне:

split -l 200000 filename

який створить файли з 200000 рядків з ім'ям xaa xab xac...

Ще один варіант, розділений на розмір вихідного файлу (все ще розпадається на розриви рядків):

 split -C 20m --numeric-suffixes input_filename output_prefix

створює файли, як output_prefix01 output_prefix02 output_prefix03 ...кожен максимум 20 мегабайт.


16
Ви також можете розділити файл за розміром: split -b 200m filename(м для мегабайт, k для кілобайт або не суфікс для байтів)
Abhi Beckert

136
розділити за розміром і забезпечити розділення файлів на розривах рядків: розділити -C 200m ім'я файлу
Клейтон Стенлі

2
спліт створює неперевершений вихід з входом Unicode (UTF-16). Принаймні на Windows з версією, яку я маю.
Вертиго

4
@geotheory, не забудьте дотримуватися порад LeberMac раніше в темі про перше перетворення закінчень рядків CR (Mac) в кінці рядків LR (Linux) за допомогою TextWrangler або BBEdit. У мене була така ж проблема, як у вас, поки я не знайшов цю пораду.
sstringer

6
-dопція недоступна в OSX, використовуйте gsplitзамість цього. Сподіваюся, це корисно для користувачів Mac.
користувач5698801


39

Так, є splitкоманда. Він розділить файл за рядками або байтами.

$ split --help
Usage: split [OPTION]... [INPUT [PREFIX]]
Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default
size is 1000 lines, and default PREFIX is `x'.  With no INPUT, or when INPUT
is -, read standard input.

Mandatory arguments to long options are mandatory for short options too.
  -a, --suffix-length=N   use suffixes of length N (default 2)
  -b, --bytes=SIZE        put SIZE bytes per output file
  -C, --line-bytes=SIZE   put at most SIZE bytes of lines per output file
  -d, --numeric-suffixes  use numeric suffixes instead of alphabetic
  -l, --lines=NUMBER      put NUMBER lines per output file
      --verbose           print a diagnostic just before each
                            output file is opened
      --help     display this help and exit
      --version  output version information and exit

SIZE may have a multiplier suffix:
b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,
GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.

Спробував georgec @ ATGIS25 ~ $ split -l 100000 /cygdrive/P/2012/Job_044_DM_Radio_Propogation/Working/FinalPropogation/TRC_Longlands/trc_longlands.txt, але в каталозі немає розділених файлів - де є вихід?
ДжорджК

1
Він повинен бути в одному каталозі. Наприклад, якщо я хочу розділити на 1 000 000 рядків на файл, зробіть наступне: split -l 1000000 train_file train_file.і в тому самому каталозі я отримаю train_file.aaз першим мільйоном, потім trail_file.abз наступним мільйоном і т. Д.
Буде

1
@GeorgeC і ви можете отримати призначені для користувача вихідні каталоги з префіксом: split input my/dir/.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

15

використання split

Розбиває файл на шматки фіксованого розміру, створює вихідні файли, що містять послідовні розділи INPUT (стандартне введення, якщо не вказано жодного або INPUT - "-")

Syntax split [options] [INPUT [PREFIX]]

http://ss64.com/bash/split.html


13

Використання:

sed -n '1,100p' filename > output.txt

Тут 1 і 100 - номери рядків, які ви будете захоплювати output.txt.


Це отримує лише перші 100 рядків, вам потрібно зафіксувати його, щоб послідовно розділити файл на наступний 101..200 тощо. Або просто використовувати, splitяк усі топ-відповіді тут уже вам розповіли.
трійка

10

розділіть файл "file.txt" на 10000 файлів рядків:

split -l 10000 file.txt

9

split(від GNU coreutils, оскільки версія 8.8 від 2010-12-22 ) включає наступний параметр:

-n, --number=CHUNKS     generate CHUNKS output files; see explanation below

CHUNKS may be:
  N       split into N files based on size of input
  K/N     output Kth of N to stdout
  l/N     split into N files without splitting lines/records
  l/K/N   output Kth of N to stdout without splitting lines/records
  r/N     like 'l' but use round robin distribution
  r/K/N   likewise but only output Kth of N to stdout

Таким чином, split -n 4 input output.буде генеруватися чотири файли ( output.a{a,b,c,d}) з однаковою кількістю байтів, але рядки можуть бути розбиті посередині.

Якщо ми хочемо зберегти повні рядки (тобто розділити на рядки), то це має працювати:

split -n l/4 input output.

Відповідна відповідь: https://stackoverflow.com/a/19031247


9

У випадку, якщо ви просто хочете розділити на x кількість рядків кожного файлу, відповіді про splitце в порядку. Але мені цікаво, що ніхто не звертав уваги на вимоги:

  • "без необхідності їх рахувати" ->, використовуючи wc ​​+ cut
  • "маючи залишок у додатковому файлі" -> split робить за замовчуванням

Я не можу це зробити без "wc + cut", але я використовую це:

split -l  $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename

Це можна легко додати до функцій bashrc, щоб ви могли просто викликати його, передаючи ім'я файлу та фрагменти:

 split -l  $(expr `wc $1 | cut -d ' ' -f3` / $2) $1

У випадку, якщо вам потрібно лише x фрагменти без залишку в додатковому файлі, просто адаптуйте формулу, щоб підсумувати її (фрагменти - 1) у кожному файлі. Я використовую такий підхід, тому що, як правило, я просто хочу x кількість файлів, а не x рядків на файл:

split -l  $(expr `wc $1 | cut -d ' ' -f3` / $2 + `expr $2 - 1`) $1

Ви можете додати це до сценарію і назвати його своїм "способом ніндзя", тому що якщо нічого не відповідає вашим потребам, ви можете побудувати його :-)


Або просто скористайтеся -nопцією split.
Аміт Найду

8

ви також можете використовувати awk

awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile

3
awk -v lines=200000 -v fmt="%d.txt" '{print>sprintf(fmt,1+int((NR-1)/lines))}'
Марк Едгар

0

HDFS отримати невеликий файл і розлився у розмір властивості.

Цей спосіб спричинить розрив рядків

split -b 125m compact.file -d -a 3 compact_prefix

Я намагаюсь зійти і розділити приблизно на 128 Мб кожен файл.

# split into 128m ,judge sizeunit is M or G ,please test before use.

begainsize=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $1}' `
sizeunit=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $2}' `
if [ $sizeunit = "G" ];then
    res=$(printf "%.f" `echo "scale=5;$begainsize*8 "|bc`)
else
    res=$(printf "%.f" `echo "scale=5;$begainsize/128 "|bc`)  # celling ref http://blog.csdn.net/naiveloafer/article/details/8783518
fi
echo $res
# split into $res files with number suffix.  ref  http://blog.csdn.net/microzone/article/details/52839598
compact_file_name=$compact_file"_"
echo "compact_file_name :"$compact_file_name
split -n l/$res $basedir/$compact_file -d -a 3 $basedir/${compact_file_name}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.