Chia: làm thế nào để chia thành tỷ lệ phần trăm khác nhau?


14

Làm cách nào tôi có thể chia tệp văn bản thành 70% và 30% bằng lệnh split?


Bạn đã kết hôn với việc sử dụng lệnh split? Nếu không, bạn có thể dễ dàng làm điều này với thao tác văn bản thẳng, chắc chắn sử dụng perl hoặc python. Miễn là tệp không quá sai, hãy đọc nó vào bộ nhớ dưới dạng một chuỗi, sau đó tách chuỗi. Nếu tệp quá lớn, thì cần nhiều công việc hơn.
Faheem Mitha

@Faheem Mitha Tập tin là 64MB. Tôi thích ý tưởng sử dụng split vì nó nhanh hơn viết mã. Bây giờ tôi đã tự hỏi nếu tôi chỉ định số lượng dòng tương ứng 70% của tệp, tôi nhận được một tệp lớn và một tệp nhỏ. Nó có nên hoạt động không?
aneuryzm

Và vâng .. nó đã hoạt động .. Tôi có nên xóa câu hỏi không?
aneuryzm

Tùy bạn, nhưng không cần thiết.
Faheem Mitha

Hãy chia sẻ câu trả lời của bạn. ( meta.stackexchange.com/questions/12513/
dogbane

Câu trả lời:


13

Các lệnh dưới đây sẽ hoạt động với tỷ lệ phần trăm trên 50% (nếu bạn chỉ muốn chia thành hai tệp), cách tiếp cận nhanh và bẩn.

1) chia 70% dựa trên các dòng

split -l $[ $(wc -l filename|cut -d" " -f1) * 70 / 100 ] filename 

2) phân chia 70% dựa trên byte

split -b $[ $(wc -c filename|cut -d" " -f1) * 70 / 100 ] filename

1
Trên MacOSX wc đôi khi trả về số lượng dòng có khoảng trắng ở trước nó, một cái gì đó phá vỡ tập lệnh này. Đường ống đầu tiên đến xargs sẽ loại bỏ những khoảng trống đó và khiến mọi thứ hoạt động trở lại: split -l $[ $(wc -l filename | xargs | cut -d" " -f1) * 70 / 100 ] filename
Emil Stenström

4

Bạn có thể sử dụng csplitđể chia thành hai phần (sử dụng bất kỳ tỷ lệ phần trăm nào), ví dụ: phần đầu tiên - 20% dòng đầu tiên, phần thứ hai - 80% dòng còn lại:

csplit infile $(( $(wc -l < infile) * 2 / 10 + 1))

$(wc -l < infile): tổng số dòng
2 / 10: phần trăm
+1: thêm một dòng vì csplitchia táchup to but not including line N

Bạn chỉ có thể phân chia dựa trên các dòng mặc dù.
Về cơ bản, miễn là bạn có số dòng thông qua $(( $(wc -l < file) * 2 / 10))bạn có thể sử dụng bất kỳ công cụ định hướng dòng nào:

sed 1,$(( $(wc -l < infile) * 2 / 10))'{
w 20-infile
d
}' infile > 80-infile

hoặc, thậm chí mát hơn:

{ head -n$(( $(wc -l < infile) * 2 / 10)) > 20-infile; cat > 80-infile; } <infile

mặc dù một số headngười câm và sẽ không tuân thủ các tiêu chuẩn nên điều này sẽ không hoạt động trên tất cả các thiết lập ...


2
{   BS=$(($(wc -c <file) * $P / 100))
    dd count=1 bs="$BS" >file1; cat
} <file >file2 2>/dev/null

... nên hoạt động cho trường hợp đơn giản này vì bạn chỉ chia tách một lần - và vì vậy có lẽ splitlà hơi quá mức. Vì vậy, miễn là các tập tin là seekable, ddsẽ chỉ làm một single read()trên <stdin, và vì vậy catcòn lại để bắt đầu của nó read()ở bất cứ điểmdd lá nó.

Nếu tệp lớn thì count=1 bs=$big_ol_numcó thể hơi khó sử dụng và nó có thể bị chặn với một số phép toán bổ sung - nhưng đơn giản -.

Một đầu vào phi seekable - như từ một đường ống - có thể nghiêng dd'kết quả s, mặc dù điều này có thể được xử lý như cũng w / GNU dd' s iflag=fullblock.


0

Đoạn mã sau sử dụng headtailhoạt động với bất kỳ tỷ lệ nào (40 đến 60 trong trường hợp này):

export FILE_NAME=train.vw
head -n $[ $(wc -l ${FILE_NAME}|cut -d" " -f1) * 40 / 100 ] ${FILE_NAME} > train_40.vw
tail -n +$[ ($(wc -l ${FILE_NAME}|cut -d" " -f1) * 40 / 100) + 1 ] ${FILE_NAME} > train_60.vw
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.