แบ่ง: วิธีการแบ่งออกเป็นเปอร์เซ็นต์ที่แตกต่างกันอย่างไร


14

ฉันจะแยกไฟล์ข้อความเป็น 70% และ 30% โดยใช้คำสั่ง split ได้อย่างไร


คุณแต่งงานแล้วโดยใช้คำสั่ง split หรือไม่? ถ้าไม่คุณสามารถทำได้อย่างง่ายดายด้วยการจัดการข้อความแบบตรงแน่นอนโดยใช้ perl หรือ python ตราบใดที่ไฟล์ไม่ผิดให้อ่านในหน่วยความจำเป็นสตริงแล้วแบ่งสตริง หากไฟล์มีขนาดใหญ่เกินไปจำเป็นต้องใช้งานมากกว่านี้
Faheem Mitha

@Faheem Mitha ไฟล์นี้เป็น 64MB ฉันชอบไอเดียที่จะใช้ split เพราะมันเร็วกว่าการเขียนโค้ด ฉันสงสัยว่าตอนนี้ถ้าฉันระบุจำนวนบรรทัดที่สอดคล้องกัน 70% ของไฟล์ฉันจะได้รับไฟล์ขนาดใหญ่และไฟล์ขนาดเล็ก มันจะไม่ทำงานเหรอ
aneuryzm

และใช่ .. ใช้งานได้ฉันควรลบคำถามหรือไม่
aneuryzm

ขึ้นอยู่กับคุณ แต่ไม่จำเป็น
Faheem Mitha

กรุณาแบ่งปันคำตอบของคุณ ( meta.stackexchange.com/questions/12513/ … )
dogbane

คำตอบ:


13

คำสั่งด้านล่างจะทำงานสำหรับเปอร์เซ็นต์ที่สูงกว่า 50% (หากคุณต้องการแบ่งออกเป็นสองไฟล์เท่านั้น) วิธีที่รวดเร็วและสกปรก

1) แบ่ง 70% ตามบรรทัด

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

2) แยก 70% ตามจำนวนไบต์

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

1
ใน MacOSX wc บางครั้งจะส่งคืนจำนวนบรรทัดด้วยช่องว่างข้างหน้าซึ่งเป็นสิ่งที่ทำให้สคริปต์นี้แตก การวางท่อครั้งแรกไปที่ xargs จะลบช่องว่างเหล่านั้นและทำให้สิ่งต่าง ๆ ทำงานได้อีกครั้ง: split -l $[ $(wc -l filename | xargs | cut -d" " -f1) * 70 / 100 ] filename
Emil Stenström

4

คุณสามารถใช้csplitเพื่อแบ่งออกเป็นสองส่วน (ใช้เปอร์เซ็นต์ใด ๆ ) เช่นชิ้นแรก - 20% แรกของบรรทัดชิ้นที่สอง - 80% ที่เหลือของบรรทัด:

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

$(wc -l < infile): จำนวนบรรทัดทั้งหมด
2 / 10: เปอร์เซ็นต์
+1: เพิ่มหนึ่งบรรทัดเนื่องจากการcsplitแยกup to but not including line N

คุณสามารถแยกได้ตามบรรทัดเท่านั้น
โดยพื้นฐานตราบใดที่คุณมีหมายเลขบรรทัดผ่าน$(( $(wc -l < file) * 2 / 10))คุณสามารถใช้เครื่องมือที่มุ่งเน้นสายใด ๆ :

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

หรือเย็นกว่า:

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

แม้ว่าบางคนheadจะโง่และไม่ปฏิบัติตามมาตรฐานดังนั้นสิ่งนี้จะไม่ทำงานในการตั้งค่าทั้งหมด ...


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

... ควรใช้กับกรณีง่าย ๆ นี้เพราะคุณแบ่งเพียงครั้งเดียว - และอาจsplitเป็นเพราะ overkill เล็กน้อย ตราบใดที่ไฟล์เป็น seekable, ddจะทำเพียงครั้งเดียวread()บน<stdinและอื่น ๆcatที่เหลืออยู่ที่จะเริ่มต้นของมันread()ที่จุดใดddใบมัน

ถ้าไฟล์มีขนาดใหญ่แล้ว count=1 bs=$big_ol_numอาจได้รับความไม่สะดวกเล็กน้อยและสามารถบล็อกออกได้โดยใช้คณิตศาสตร์เชลล์พิเศษ

การป้อนข้อมูลที่ไม่ใช่ seekable - เช่นจากท่อ - อาจเอียงdd's ผลแม้ว่าจะสามารถจัดการได้เป็นอย่างดี w / GNU dd' iflag=fullblocks


0

รหัสต่อไปนี้ใช้headและtailทำงานร่วมกับอัตราส่วนใด ๆ (40 ถึง 60 ในกรณีนี้):

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