จะแบ่งไฟล์ข้อความขนาดใหญ่เป็นไฟล์ขนาดเล็กลงด้วยจำนวนบรรทัดเท่ากันได้อย่างไร


515

ฉันมีไฟล์ข้อความธรรมดาขนาดใหญ่ (ตามจำนวนบรรทัด) ที่ฉันต้องการแยกเป็นไฟล์ขนาดเล็กลงเช่นกันตามจำนวนบรรทัด ดังนั้นหากไฟล์ของฉันมีประมาณ 2M บรรทัดฉันต้องการแยกมันเป็น 10 ไฟล์ที่มี 200k lines หรือ 100 ไฟล์ที่มี 20k lines (บวกหนึ่งไฟล์ที่มีส่วนที่เหลือการแบ่งเท่ากันไม่สำคัญ)

ฉันสามารถทำสิ่งนี้ได้อย่างง่ายดายใน Python แต่ฉันสงสัยว่ามีวิธีใดในการทำเช่นนี้โดยใช้ bash และ unix utils (ซึ่งต่างจากการวนซ้ำด้วยตนเอง


2
ด้วยความอยากรู้อยากเห็นหลังจากที่พวกเขา "แยก" คนหนึ่ง "รวม" พวกเขาได้อย่างไร บางอย่างเช่น "cat part2 >> part1" หรือจะมียูทิลิตี้นินจาอีกอัน? ต้องการอัปเดตคำถามของคุณหรือไม่
dlamotte

7
เพื่อนำมันกลับมารวมกันcat part* > original
Mark Byers

9
ใช่แมวสั้นสำหรับการต่อกัน โดยทั่วไปแล้วมีประโยชน์สำหรับการค้นหาคำสั่งที่เหมาะสม IE ดูผลลัพธ์ของ:
apropos

@pixelbeat มันเจ๋งมากขอบคุณ
danben

3
นอกจากนี้ผู้ใช้ OS X ควรตรวจสอบให้แน่ใจว่าไฟล์ของพวกเขามีตัวแบ่งบรรทัด LINUX หรือ UNIX สไตล์ / ตัวบ่งชี้สิ้นสุดบรรทัด (LF) แทน MAC OS X - ตัวบ่งชี้สิ้นสุดบรรทัด (CR) - ตัวแยกและ คำสั่ง csplit จะไม่ทำงานหากการแบ่งที่คุณชอบเป็น Carriage Returns แทนที่จะเป็น LineFeeds TextWrangler จากซอฟต์แวร์ BareBones สามารถช่วยคุณได้หากคุณใช้ Mac OS คุณสามารถเลือกวิธีที่คุณต้องการให้ตัวละครของคุณแบ่งบรรทัด เมื่อคุณบันทึก (หรือบันทึกเป็น ... ) ไฟล์ข้อความของคุณ

คำตอบ:


856

คุณดูที่คำสั่ง 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 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

ซึ่งจะสร้างไฟล์แต่ละไฟล์ที่มีชื่อ 200,000 บรรทัดxaa xab xac...

ตัวเลือกอื่นแยกตามขนาดของไฟล์เอาต์พุต (ยังแยกตามตัวแบ่งบรรทัด):

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

สร้างไฟล์เช่นoutput_prefix01 output_prefix02 output_prefix03 ...ขนาดสูงสุด 20 เมกะไบต์แต่ละไฟล์


16
คุณยังสามารถแบ่งไฟล์ตามขนาด: split -b 200m filename(m สำหรับเมกะไบต์, k สำหรับกิโลไบต์หรือไม่มีส่วนต่อท้ายเป็นไบต์)
Abhi Beckert

136
แยกตามขนาดและตรวจสอบให้แน่ใจว่าไฟล์ถูกแยกในการขึ้นบรรทัดใหม่: ชื่อไฟล์ Split -C 200m
Clayton Stanley

2
Split สร้างเอาต์พุตที่อ่านไม่ออกด้วยอินพุต Unicode (UTF-16) อย่างน้อยบน Windows กับรุ่นที่ฉันมี
Vertigo

4
@geotheory ตรวจสอบให้แน่ใจว่าได้ทำตามคำแนะนำของ LeberMac ก่อนหน้าในหัวข้อเกี่ยวกับการแปลงบรรทัด CR (Mac) ตอนแรกให้เป็น LR (Linux) สิ้นสุดบรรทัดโดยใช้ TextWrangler หรือ BBEdit ฉันมีปัญหาเดียวกันกับคุณจนกว่าฉันจะพบคำแนะนำนั้น
sstringer

6
-dตัวเลือกไม่พร้อมใช้งานบน OSX ใช้gsplitแทน หวังว่าสิ่งนี้มีประโยชน์สำหรับผู้ใช้ Mac
user5698801


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 ~ $ แยก -l 100000 /cygdrive/P/2012/Job_044_DM_Radio_Propogation/Working/FinalPropogation/TRC_Longlands/trc_longlands.txt แต่ไม่มีไฟล์ที่แยกในไดเรกทอรี - ที่ใดที่เป็นเอาต์พุต?
GeorgeC

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คำตอบยอดนิยมทั้งหมดที่นี่บอกคุณแล้ว
tripleee


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จะเป็น OK แต่ฉันอยากรู้เกี่ยวกับไม่มีใครใส่ใจกับข้อกำหนด:

  • "โดยไม่ต้องนับ" -> ใช้ wc + cut
  • "การมีส่วนที่เหลือเป็นไฟล์พิเศษ" -> การแยกทำตามค่าเริ่มต้น

ฉันไม่สามารถทำเช่นนั้นได้หากไม่มี "wc + cut" แต่ฉันกำลังใช้งานอยู่:

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

สิ่งนี้สามารถเพิ่มลงในฟังก์ชั่น bashrc ของคุณได้อย่างง่ายดายดังนั้นคุณสามารถเรียกมันผ่านชื่อไฟล์และชิ้นส่วน:

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

ในกรณีที่คุณต้องการ x chunks ที่ไม่มีเศษเหลือในไฟล์พิเศษให้ปรับสูตรเพื่อรวม (chunks - 1) ในแต่ละไฟล์ ฉันใช้วิธีการนี้เพราะโดยปกติฉันต้องการ x จำนวนไฟล์มากกว่า x lines ต่อไฟล์:

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

คุณสามารถเพิ่มมันลงในสคริปต์และเรียกมันว่า "วิธีนินจา" ของคุณเพราะถ้าไม่มีอะไรที่ตรงกับความต้องการของคุณคุณสามารถสร้างมันได้ :-)


หรือเพียงแค่ใช้ตัวเลือกในการ-n split
Amit Naidu


0

HDFS getmerge ไฟล์ขนาดเล็กและหกลงในขนาดคุณสมบัติ

วิธีนี้จะทำให้เส้นแบ่ง

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

ฉันพยายาม getmerge และแบ่งเป็นประมาณ 128MB ทุกไฟล์

# 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}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.