เลือกแทนการค้นหาและแทนที่บรรทัดที่ยาวมาก


9

ฉันมีไฟล์ที่สร้างขึ้นโดยโปรแกรมที่ไม่ได้ขึ้นบรรทัดใหม่เมื่อสิ้นสุดการบันทึก ฉันต้องการขึ้นบรรทัดใหม่ระหว่างระเบียนและฉันสามารถทำได้ด้วยสคริปต์แบบง่าย:

sed -e 's/}{/}\n{/g'

ปัญหาคือไฟล์อินพุตมีขนาดหลายกิกะไบต์และดังนั้นบรรทัดอินพุตเป็น sed มีความยาวหลาย GB sed พยายามเก็บสายไว้ในหน่วยความจำซึ่งไม่สามารถใช้งานได้ในกรณีนี้ ฉันลองใช้--unbufferedตัวเลือก แต่ดูเหมือนว่าจะทำให้ช้าลงและไม่อนุญาตให้ทำอย่างถูกต้อง


เป็นไปได้ไหมที่จะอัปโหลดไฟล์อินพุตตัวอย่างที่เราลองใช้แนวคิด
mkc

3
บางทีคุณอาจจะเป็นครั้งแรกสามารถใช้trในการแปล}ลงใน\nและจากนั้นใช้sedเพื่อเพิ่ม}ตอนท้ายของแต่ละเส้น? เช่นนี้:tr '}' '\n' < your_file.txt| sed 's/$/}/'
user43791

การเพิ่มบรรทัดใหม่ในตอนท้ายของไฟล์ช่วยได้หรือไม่? ไลค์:printf "\n" >> file
พี่เลี้ยงเด็ก

1
@ Ketan ฉันถือว่าการเขียนไฟล์ที่มีตัวอักษรขยะ 78 ตัวตามด้วยการ}{ทำซ้ำจนกว่าไฟล์จะมีความยาวหลายกิกะไบต์
พี่เลี้ยง

@ พี่เลี้ยง - จุดดี - แต่คุณจะได้ 78 หากบันทึกถูกปิดกั้นแล้วก็dd if=file cbs=80 conv=unblockจะทำเช่นนั้น - แต่มันก็ไม่ง่ายอย่างนั้น
mikeserv

คำตอบ:


7

คุณสามารถใช้เครื่องมืออื่นที่ช่วยให้คุณตั้งค่าตัวคั่นเร็กคอร์ดอินพุต ตัวอย่างเช่น

  • Perl

    perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
    

    ตัวแปรพิเศษ$/คือตัวคั่นเรคคอร์ดอินพุต การตั้งค่าให้}{นิยามบรรทัดที่ลงท้าย}{ด้วย ด้วยวิธีนี้คุณสามารถบรรลุสิ่งที่คุณต้องการโดยไม่ต้องอ่านสิ่งทั้งหมดลงในความทรงจำ

  • เหยี่ยวหรือเหยี่ยว

    awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file 
    

    นี่คือความคิดเดียวกัน RS="}{"ตั้งค่าตัวคั่นเรกคอร์ดเป็น}{แล้วคุณพิมพ์}บรรทัดใหม่{(ยกเว้นสำหรับระเบียนแรก) และระเบียนปัจจุบัน


3

Perl เพื่อช่วยเหลือ:

perl -i~ -e ' $/ = \1024;
              while (<>) {
                  print "\n" if $closing and /^{/;
                  undef $closing;
                  s/}{/}\n{/g;
                  print;
                  $closing = 1 if /}$/;
              } ' input1 input2

การตั้งค่า$/เป็น\1024จะอ่านไฟล์เป็นหน่วย 1024 ไบต์ $closingตัวแปรจับกรณีที่ก้อนปลายในและถัดไปจะเริ่มต้นด้วย}{


1
+1 อาจเป็นทางออกที่ดีที่สุด โซลูชัน perl / awk อื่น ๆ ทำงานได้ดีเช่นกัน แต่จะเกิดอะไรขึ้นถ้าตัวแยกเรคคอร์ดแรกเกิดขึ้นหลังจากมูลค่าตัวอักษรประมาณ 17GB
don_crissti

2

คุณควรทำ:

{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile

มันอาจเป็นทางออกที่มีประสิทธิภาพที่สุด

ที่ทำให้{}เพื่อป้องกันข้อมูลต่อท้ายที่เป็นไปได้ ด้วยtrกระบวนการอีกหนึ่งคุณสามารถสลับที่รอบ ๆ และทำบรรทัดว่างที่ส่วนหัวของ{ฟิลด์แรก ชอบ...

tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}

ดังนั้นข้อมูลแรกจากตัวอย่างของ don:

printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; }           |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}

... และอันที่สองทำ ...

printf '{one}{two}{three}{four}'      |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}

ไม่มีการขึ้นบรรทัดใหม่สำหรับตัวอย่างที่สอง - แม้ว่าจะมีการขึ้นบรรทัดใหม่สำหรับครั้งแรก


0

sedยูทิลิตี้เหมือนไบนารีที่เรียกว่าbbe

ฉันคิดว่ามันง่ายที่สุดที่จะอยู่กับไวยากรณ์แบบ sed ในกรณีนี้

ฉันมากต้องการใช้bbeยูทิลิตี้ (สามารถใช้ได้ผ่านทางคุณ {เดียว, Linu} ติดตั้งแพคเกจ x ของ EQ apt-get) หรือที่นี่ถ้าคุณเป็นหนึ่งในฝูงชนคอมไพล์แม้ว่าฉันจะไม่ได้ตรวจสอบลิงก์นั้นเป็นการส่วนตัว

1. มันรองรับs/before/after/สำนวน

มันเป็น "Binary Block Editor" ซึ่งรองรับการทำงานที่เหมือนอยู่ในใจ ซึ่งรวมถึงs/before/after/สำนวนการแทนที่ธรรมดาที่คุณต้องการ หมายเหตุเนื่องจากไม่มีbbeมุมมองต่อบรรทัดจึงไม่มี "global g" ที่ส่วนท้ายของคำสั่ง

เป็นการทดสอบอย่างรวดเร็ว (หมายเหตุจำเป็น-e):

$ echo hello | bbe -e 's/l/(replaced)/'

ผลิต:

he(replaced)(replaced)o

2. ในกรณีที่คุณ}{ต้องการ}\n{แปลง

ดังนั้นหากเรามีไฟล์ขนาดใหญ่ที่เต็มไปด้วยตัวเลขล้านใน (พูด) รูปแบบ{1}{2}{3}... {1000000}โดยไม่มีการขึ้นบรรทัดใหม่เราสามารถแลกเปลี่ยน}{กับ}\n{ได้อย่างง่ายดายและมีตัวเลขทั้งหมดหนึ่งต่อบรรทัด

นี่จะเป็นด้วยbbeคำสั่งนี้:

bbe -e 's/}{/}\n{/'

ดังที่ได้ทดสอบในลูป zsh นี้ซึ่งเราคว้าได้แค่:

$ for ((num=0; num<1000000; num++)) do; echo -n "{$num}"; done | bbe -e 's/}{/}\n{/' | tail

ซึ่งจะผลิตสิ่งนี้:

{999990}
{999991}
{999992}
{999993}
{999994}
{999995}
{999996}
{999997}
{999998}
{999999}

(โดยไม่ต้องมีการปัดแคร่กลับ)

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