Làm cách nào để chia tệp CSV theo số hàng được chỉ định?


83

Tệp CSV của tôi (khoảng 10.000 hàng; mỗi hàng có 300 cột) được lưu trữ trên máy chủ LINUX. Tôi muốn chia tệp CSV này thành 500 tệp CSV gồm 20 bản ghi mỗi tệp. (Mỗi có cùng một tiêu đề CSV như hiện tại trong CSV gốc)

Có lệnh linux nào để giúp chuyển đổi này không?


1
Điều này thực sự hoạt động, tuy nhiên, tiêu đề của tệp đầu tiên sẽ được sao chép do đó tạo ra 2 tiêu đề tệp csv đầu tiên.
rickman,


Câu trả lời:


79

Đã biến nó thành một hàm. Bây giờ bạn có thể gọisplitCsv <Filename> [chunkSize]

splitCsv() {
    HEADER=$(head -1 $1)
    if [ -n "$2" ]; then
        CHUNK=$2
    else 
        CHUNK=1000
    fi
    tail -n +2 $1 | split -l $CHUNK - $1_split_
    for i in $1_split_*; do
        sed -i -e "1i$HEADER" "$i"
    done
}

Tìm thấy trên: http://edmondscommerce.github.io/linux/linux-split-file-eg-csv-and-keep-header-row.html


1
Bạn có thể giải thích cách hoạt động của nó không? Tôi đã kiểm tra bài đăng gốc nhưng cũng không có lời giải thích nào, và thậm chí không có tùy chọn để đăng bình luận.
shashi009 10/06/16

6
điều gì sẽ xảy ra nếu một ô trong CSV chứa một dòng mới?
Ondřej Hlaváček

Loại ký tự dòng mới là gì? Nó vẫn hoạt động đối với tôi, trên UTF-8, không chắc liệu điều này có hữu ích hay không.
owyongsk

3
@ shashi009: Giả sử tệp gốc được gọi là file.txt. 1: bỏ qua dòng đầu tiên, sau đó chuyển phần còn lại của tệp vào split, chia thành các tệp mới, mỗi tệp dài 20 dòng, với tiền tố split_2: lặp qua các tệp split_ * mới, lưu trữ từng tên cho biến file, mỗi lần một 3: cho mỗi ... 4: ghi dòng đầu tiên (tiêu đề cột) từ tệp gốc của chúng tôi thành tệp tmp_file 5: nối tệp chia 20 dòng thành tmp_file 6: ghi đè tệp split_ * cũ bằng tệp mới tmp_file, vì vậy nó giữ nguyên tiêu đề cột
David

1
Việc thêm tiêu đề qua echo -e "$HEADER\n$(cat $i)" > $ilà không phù hợp một cách không cần thiết. Tôi đã thay thế nó bằng sed -i -e "1i$HEADER" "$i".
Philipp Moers

146

Sử dụng lệnh tách Linux:

split -l 20 file.txt new    

Chia tệp "file.txt" thành các tệp bắt đầu bằng tên "mới", mỗi tệp chứa 20 dòng văn bản.

Nhập man splitvào dấu nhắc Unix để biết thêm thông tin. Tuy nhiên, trước tiên bạn sẽ phải xóa tiêu đề khỏi file.txt ( tailví dụ: bằng cách sử dụng lệnh) và sau đó thêm lại nó vào từng tệp được tách.


Làm cách nào để bỏ qua dòng đầu tiên (tiêu đề) của file.txt?
forkfork

sử dụng wc -lđể lấy số dòng, sau đó lấy giá trị này trừ đi 1 (giả sử là wc -l50) và sau đó chạy tail -n 49(trong ví dụ này) để lấy mọi thứ ngoại trừ dòng tiêu đề. Lưu ý rằngwc -l đếm các ký tự <newline>, vì vậy nếu dòng cuối cùng không kết thúc bằng ký tự dòng mới, bạn sẽ bị lệch 1 trong số dòng của mình.
Lucas Roberts

4
@lucas, tail -n +2 sẽ in tất cả các dòng trừ dòng đầu tiên.
James King,

@JamesKing, +1 & Cảm ơn! Tôi nên đọc tài liệu kỹ hơn :)
Lucas Roberts

6
để giữ ".csv" trong các tệp mới chỉ cần thêm--additional-suffix=.csv
Cocuba

21

Điều này sẽ hoạt động !!!

file_name= Tên của tệp bạn muốn tách.
10000= Số hàng mà mỗi tệp được tách sẽ chứa
file_part_= Tiền tố của tên tệp được tách (tệp_part_0, tệp_part_1, tệp_part_2..vv tiếp tục)

split -d -l 10000 file_name.csv file_part_


điều này hoạt động hoàn toàn tốt! Có cách nào để tôi có thể giới hạn số lượng 10000 tệp hàng mà tôi tạo không. Giả sử tôi chỉ muốn 200.000 hàng đầu tiên được chia thành các tệp csv 10k hàng và bỏ qua phần còn lại.
Pronomita Dey

1
@Pronomitahead -200000 file.csv | split -l 10000 - new_
boloyao

2
Tôi có một tệp CSV 13 Gb với một dòng bị hỏng ở khoảng dòng ~ 69 000 000. Nó đang chặn việc nhập vào bigquery. Điều này cho phép tôi tách nó một cách đệ quy cho đến khi tôi có thể tách dòng và sửa chữa nó. Không có giải pháp nào khác hiệu quả trong việc xử lý các tệp lớn mà không làm sập máy chủ hoặc khóa mọi thứ. Mất khoảng 2 phút để chia tệp thành 5.000.000 khối hàng. Cảm ơn!
LP Papillon

13

Điều này sẽ làm điều đó cho bạn - tất cả các tệp của bạn sẽ được gọi là Part1-Part500.

#!/bin/bash
FILENAME=10000.csv
HDR=$(head -1 $FILENAME)   # Pick up CSV header line to apply to each file
split -l 20 $FILENAME xyz  # Split the file into chunks of 20 lines each
n=1
for f in xyz*              # Go through all newly created chunks
do
   echo $HDR > Part${n}    # Write out header to new file called "Part(n)"
   cat $f >> Part${n}      # Add in the 20 lines from the "split" command
   rm $f                   # Remove temporary file
   ((n++))                 # Increment name of output part
done

Điều này tạo ra các tập tin nhưng các tab (Tôi có nghĩa là \ t) được thay thế bằng không gian, và các tập tin CSV của tôi đang sử dụng \ t như tách
AmineG

Điều này có thể được cải thiện một chút bằng cách đệm các số để các tệp được hiển thị liên tiếp một cách tự động. Bằng cách thay thế $ {n} bằng $ (printf "% 05d \ n" $ n)
Phineas Dashevsky

4
Dòng tiêu đề được sao chép trong tệp đầu tiên.
Juha Palomäki

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.