ฉันมีไฟล์บันทึก 8 Gb (บันทึกการผลิตของ Rails) ฉันต้องตัดมันระหว่างวันที่ (เส้น) ฉันสามารถใช้คำสั่งใดในการทำสิ่งนี้
sed
จะทำได้อย่างง่ายดาย
ฉันมีไฟล์บันทึก 8 Gb (บันทึกการผลิตของ Rails) ฉันต้องตัดมันระหว่างวันที่ (เส้น) ฉันสามารถใช้คำสั่งใดในการทำสิ่งนี้
sed
จะทำได้อย่างง่ายดาย
คำตอบ:
สิ่งที่ต้องการ
sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less
tee cut-log
cut-log
ช่วยให้คุณสามารถเห็นบนหน้าจอสิ่งที่จะถูกใส่ในแฟ้ม
แก้ไข:
เพื่อให้เป็นไปตามมาตรฐานที่เข้มงวดของ fred.bear ต่อไปนี้เป็นวิธีการแก้ปัญหาที่น่ากลัว (แม้ว่าเนื้อหาวิธีแก้ปัญหา awk จะสวยกว่ามาก):
b=BB; e=EE ;echo -e "AA\nAA\nBB\nBB\nCC\nCC\nDD\nDD\nEE\nEE\nFF\nFF" | sed -n ":b;/$b/b p;n;b b;:p;p;n;/$e/b e;b p;:e;p;n;/$e/b e;q"
sed
สามารถจับคู่กับawk
ความเร็วได้และเร็วขึ้นเล็กน้อย
สิ่งนี้จะทำสิ่งที่คุณต้องการ ...
ทั้งการรวมและไม่รวมวันที่พารามิเตอร์จะแสดงขึ้น
# set Test args
set 2011-02-24 2011-02-26 "junk"
from="$1"
till="$2"
file="$3"
# EITHER ==== +++++++++
# Ouptut lines between two parameter dates INCLUDING the parameter dates
awk -v from=$from -v till=$till '
($2 >= from) && ($2 <= till) { print $0 ; next }
($2 > till) { exit }' "$file"
# OR ======== ---------
# Ouptut lines between two parameter dates EXCLUDING the parameter dates
awk -v from=$from -v till=$till '
($2 > from) && ($2 < till) { print $0 ; next }
($2 >= till) { exit }' "$file"
มันทดสอบสำหรับวันที่ (เรียงลำดับ) ในฟิลด์ 2 ... นี่คือตัวอย่างสำหรับข้อมูลการทดสอบ
98 2011-02-05 xxxx
99 2011-02-05 xxxx
100 2011-02-06 xxxx
101 2011-02-06 xxxx
awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
if
คำสั่งทั้งหมด (ไม่แม้แต่ 1 ต่อบรรทัด) เช่น ตรรกะไหลเหมือนกันอย่างมีประสิทธิภาพและความแตกต่างในเวลาทำงานจะถูกนับเป็น nanoseconds .... เหตุผลเดียวที่ฉันไม่ได้ใช้ "อื่น" คือว่านี่เป็นawk
สคริปต์แรกของฉันที่มีประสิทธิภาพ(นอกเหนือจากหนึ่งวัน 4 ปี ที่ผ่านมาเมื่อฉันเล่นกับตัวอย่าง) ... และนั่นคือกลไกสาขาที่สามารถทำงานได้ครั้งแรกที่ฉันพบ ... (และตามที่กล่าวไว้มันเป็นไปอย่างรวดเร็ว) .. ฉันมักจะใช้sed
ลองq
หากในไฟล์บันทึกของคุณคุณมีวันที่ในรูปแบบนี้YYYY-MM-DD
ดังนั้นเมื่อต้องการค้นหารายการทั้งหมดสำหรับพูด 2011-02-10 คุณสามารถทำได้:
grep 2011-02-10 log_file
ตอนนี้ถ้าคุณต้องการค้นหารายการสำหรับ 2011-02-10 และ 2011-02-11 ให้ใช้อีกครั้งgrep
แต่มีหลายรูปแบบ:
grep -E '2011-02-10|2011-02-11' log_file
grep
จะค้นหาไฟล์ทั้งหมดแม้ว่าช่วงวันที่จะเป็นจุดเริ่มต้นของไฟล์ โดยเฉลี่ยนี้จะเพิ่มเวลาการค้นหาเป็นสองเท่าเมื่อเปรียบเทียบกับ "exit-after-last-item-in-range" ... ฉันแค่อยากจะพูดถึงสิ่งนี้เพราะขนาดไฟล์ 8 GB ที่กล่าวถึงในคำถามของคุณ ผลลัพธ์เวลา grep เกือบเหมือนตัวอย่าง sed ที่นี่ (1 นาที 58 วินาที) นี่คือลิงค์ไปยังผลการทดสอบเวลาของฉัน: paste.ubuntu.com/573477
การทำงานกับไฟล์ขนาดนี้เป็นเรื่องยากเสมอ
วิธีข้างหน้าอาจแบ่งไฟล์นี้ออกเป็นไฟล์เล็ก ๆ สองสามไฟล์เพื่อทำสิ่งนี้คุณสามารถใช้คำสั่ง split
split -d -l 50000 ToBigFile.data file_
แม้เจ้ามันจะถูกแยกออกคุณยังสามารถทำงานกับไฟล์ได้เหมือนจะเป็นไฟล์ที่ใช้ bash for loop
for f in `ls file_*`; do cat $f; done;
แต่แทนที่จะเป็นแมวคุณสามารถใช้ grep คว่ำเพื่อกำจัดข้อมูลที่ไม่ต้องการซึ่งไม่เกี่ยวข้องสำหรับสิ่งนี้ (หรือประเภทของการปรับแต่งที่คุณต้องการ)
ณ จุดนี้คุณจะทำงานกับไฟล์ขนาดเล็กจำนวนมากและคำสั่งอื่น ๆ ที่กล่าวถึงข้างต้นจะทำงานในไฟล์ขนาดเล็กจำนวนมาก
และเมื่อคุณทำเสร็จแล้วคุณสามารถใช้ครั้งที่สองสำหรับการวนซ้ำเพื่อสร้างไฟล์ขนาดเล็กลงใหม่อีกครั้ง
for f in `ls file_*`; do cat $f >> NewFile.data ; done;
อัปเดต เนื่องจากเราเริ่มแบ่งข้อมูลออกเป็นหลายไฟล์จึงมีงานจำนวนมากกับฮาร์ดไดรฟ์และต้องใช้เวลา (ในคำถามนี้เห็นได้ชัดว่า 5 นาที)
ในอีกทางหนึ่งขั้นตอนต่อไปอาจจะเร็วกว่า
ดังนั้นวิธีนี้อาจไม่มีจุดหมายสำหรับการดำเนินการ grep, awk, sed แบบง่าย ๆ แต่ถ้ารูปแบบการค้นหาซับซ้อนมากขึ้นมันอาจกลายเป็นเร็วขึ้น
perl -wlne '/^2011-02-24/ .. /^2011-02-25/ and print' log_file