การแทนที่สตริงในไฟล์ที่มีขนาดใหญ่มาก


10

ฉันมี URL จำนวนมากที่ไม่มีตัวคั่นในรูปแบบเดียวกับด้านล่าง:

http://example.comhttp://example.nethttp://example.orghttp://etc...

ฉันต้องการให้แต่ละ URL อยู่ในบรรทัดใหม่ ฉันพยายามทำสิ่งนี้โดยแทนที่ "http: //" ด้วย "\ nhttp: //" โดยใช้ sed

sed 's_http://_\nhttp://_g' urls.txt

แต่เกิดข้อผิดพลาดในการแบ่งกลุ่ม (การละเมิดหน่วยความจำ) ฉันสามารถคาดเดาได้ว่าขนาดไฟล์ที่แท้จริง (เกิน 100GB) ทำให้เกิดความผิดเพี้ยนเกินขีด จำกัด

ฉันสามารถแบ่งไฟล์ออกเป็นไฟล์เล็ก ๆ หลาย ๆ ไฟล์เพื่อการประมวลผลได้ แต่อินสแตนซ์ทั้งหมดของ "http: //" จะต้องถูกเก็บรักษาไว้เหมือนเดิม

มีวิธีที่ดีกว่าในการทำเช่นนี้?


ฉันคิดว่า sed ไม่ชอบ 100GB ที่ไม่มีจุดสิ้นสุดของบรรทัดเนื่องจากพยายามอ่านบรรทัดเดียวในบัฟเฟอร์
jippie

แยก (โดยไม่คำนึงถึง "ที่" ตัดเกิดขึ้น) การประมวลผลแล้วประกอบกันอีกครั้งควรให้ แต่ผลลัพธ์ที่ถูกต้อง
enzotib

3
หากคุณมีไฟล์ข้อความขนาด 100GB ที่มีเส้นยาวหนึ่งบรรทัดคุณควรเขียนโปรแกรม C ด่วนเพื่อใช้งาน
fpmurphy

คำตอบ:


11

ด้วยawkคุณสามารถหลีกเลี่ยงการอ่านข้อความจำนวนมากในครั้งเดียว:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt

ความสำเร็จอาจขึ้นอยู่กับการใช้awkงานที่ใช้ ตัวอย่างเช่นใช้gawkงานได้ดี แต่mawkล้มเหลว


6

สิ่งนี้จะทำงาน:

perl -pe 'BEGIN { $/ = "//" } s!(?=http://\z)!\n!' urls.txt

โดยการตั้งค่า$ /ฉันได้เปลี่ยนคำจำกัดความของบรรทัดดังนั้นมันจึงลงท้ายด้วย//แทนที่จะขึ้นบรรทัดใหม่ สิ่งนี้ทำให้ Perl อ่านทีละหนึ่ง URL ไม่น่าเป็นไปได้ที่ URL จะมี//ยกเว้นหลังจากโครงร่าง แต่ก็โอเคถ้ามี Regex จะป้องกันไม่ให้เพิ่มบรรทัดใหม่ปลอม

หากคุณต้องการหลีกเลี่ยงการเพิ่มบรรทัดว่างหน้า URL แรก:

perl -pe 'BEGIN { $/ = "//"; print scalar <> } s!(?=http://\z)!\n!' urls.txt

คุณอาจลองเปรียบเทียบเพื่อดูว่าs!http://\z!\nhttp://!เร็วขึ้นหรือไม่ พวกมันเทียบเท่ากัน โปรดทราบว่าการ/gตั้งค่าสถานะไม่จำเป็นสำหรับการทดแทนเนื่องจากสามารถมีได้เพียงหนึ่งรายการต่อหนึ่งรายการ "บรรทัด"


โปรแกรม perl regexp นั้นโอเคกับเส้นหลายกิกะไบต์หรือไม่?
Alexios

2
@Alexios อาจจะไม่ แต่ก็ไม่จำเป็นต้องเป็น ตั้งแต่ฉันเปลี่ยน$/มันจะจัดการกับ URL ทีละรายการเท่านั้น
cjm

อาฉันเห็นสิ่งที่คุณทำที่นั่น เป็นเวลานานแล้วตั้งแต่ยุค 90 และฉันก็ต้องทำman perlvarแต่มันก็สมเหตุสมผลดี
Alexios

Linux อนุญาตให้ URL ฝังตัวหลายสแลชในพา ธ ดังนั้นรหัสนี้อาจล้มเหลวหากคุณมีสิ่งเหล่านี้ การทดสอบสตริงทั้งหมด http และทั้งหมดจะไม่มีปัญหานี้
โจ

@ โจฉันกำลังทดสอบhttp:ส่วนใน regex มันจะตรวจสอบทุกแต่มันจะไม่เพิ่มขึ้นบรรทัดใหม่จนกว่าจะพบ// http://
cjm

5
  1. เปลี่ยนการเกิดขึ้นทั้งหมด:ด้วย a ขึ้นบรรทัดใหม่เพื่อตัดไฟล์
  2. แทนที่
    • http ในตอนท้ายของบรรทัดด้วย
    • ขึ้นบรรทัดใหม่แล้วhttp:ต่อท้ายบรรทัดถัดไป
  3. ทำซ้ำหนึ่งครั้งดังนั้นแม้กระทั่งและมีการอัพเดทบรรทัดคี่

ขั้นตอนเหล่านี้มีลักษณะดังนี้:

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. ตรวจสอบว่ามีบรรทัดที่ไม่ได้เริ่มต้นด้วยhttp://พิมพ์หมายเลขบรรทัด นี้เท่านั้นที่จะเกิดขึ้นหาก: เป็นหนึ่งใน URL อื่น ๆ httpกว่าหลังจากที่

    grep -nv '^http://'

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