แทนที่หลายบรรทัดในไฟล์ข้อความด้วยรูปแบบคงที่


2

โอเคกำลังมองหาวิธีที่รวดเร็วในการทำสิ่งนี้ ฉันมีรายการหมายเลขบรรทัดที่ต้องเปลี่ยนแปลงในไฟล์ข้อมูลตัวอักษร รูปแบบ 16 บิตในบรรทัดนั้นสามารถเป็นอะไรก็ได้ แต่ฉันต้องเปลี่ยนเพื่อเปลี่ยนเป็นอ่านXXXXXXXXXXXXXXXXตามหมายเลขบรรทัดเท่านั้น อีกครั้งฉันมีรายการหมายเลขบรรทัดยาวฉันรู้ว่าจำเป็นต้องเปลี่ยน ไม่มีรูปแบบที่สังเกตเห็นได้สำหรับบรรทัดที่จำเป็นต้องเปลี่ยน (ฉันไม่ได้เขียนรูปแบบข้อมูล แต่ฉันรู้ว่าต้องเปลี่ยนบรรทัดใดเพื่ออ่าน X ทั้งหมด) ฉันอ่านคำตอบมากมายที่นี่และไม่มีใครจัดการเรื่องนี้ได้

หากยังไม่ชัดเจนฉันจะใช้อีกวิธีหนึ่ง ...

เปลี่ยนสาย 26115, 32198, 37256, 40001, 40023 XXXXXXXXXXXXXXXในแฟ้มที่จะอ่าน ฉันมีมากกว่า 100,000 บรรทัดที่ต้องเปลี่ยนไฟล์ 1.9 ล้านบรรทัด

คำตอบ:


3

เป็นส่วนขยายของคำตอบของ @ Gilles เนื่องจากคุณบอกว่าคุณมีหมายเลขบรรทัดที่ต้องการเปลี่ยนแปลงในไฟล์ (ซึ่งฉันจะถือว่าเรียงและเรียกlinums)

awk '
  BEGIN { getline NEXT < "linums" }
  NR == NEXT { $0 = "XXXXXXXXXXXXXXX"; getline NEXT < "linums" }
  1
'

วิธีนี้ช่วยลดการเปลี่ยนหลายพันบรรทัดได้โดยไม่ต้องพิมพ์ตัวเลขหลายพันบรรทัดด้วยตนเอง

stdinอีกทางเลือกหนึ่งที่มีการปรับเปลี่ยนเล็กน้อยคุณสามารถใช้อย่างใดอย่างหนึ่งหมายเลขบรรทัดหรือไฟล์ที่จะเปลี่ยน ฉันจะสร้างสคริปต์สำหรับสิ่งนี้ (ฉันเรียกว่าredact.awk)

#!/usr/bin/awk -f
BEGIN {
    LINUMS = ARGV[1]
    ARGV[1] = ARGV[2]
    --ARGC
    getline NEXT < LINUMS
}
NR == NEXT {
    $0 = "XXXXXXXXXXXXXXX"
    getline NEXT < LINUMS
}
1

จากนั้นคุณสามารถใช้:

$ ./redact.awk linums file-to-be-changed
$ ./redact.awk - file-to-be-changed
$ ./redact.awk linums -
$ ./redact.awk linums

(สองอันสุดท้ายเทียบเท่ากัน)


2

sed หรือ awk ทำงานได้ดีสำหรับภารกิจนี้

sed '
    26115 s/.*/XXXXXXXXXXXXXXX/
    32198 s/.*/XXXXXXXXXXXXXXX/
    37256 s/.*/XXXXXXXXXXXXXXX/
    40001 s/.*/XXXXXXXXXXXXXXX/
    40023 s/.*/XXXXXXXXXXXXXXX/
'
awk '
  NR==26115 || NR==32198 || NR==37256 || NR==40001 || NR==40023 {$0 = "XXXXXXXXXXXXXXX"}
  1
'

(โลน1พิมพ์ทุกบรรทัดหลังจากการแปลงที่เป็นไปได้ซึ่งดำเนินการโดยรหัสก่อนหน้า)


ฉันคิดว่าฉันจะไปด้วยโซลูชัน sed เพราะฉันมีหมายเลขบรรทัดในไฟล์แล้ว ขอบคุณสำหรับการตอบสนองอย่างรวดเร็ว. การแก้ปัญหา awk จะพิมพ์มากเกินไป :)
Thorne Kontos

2
sed -e '1{x;s/^/XXXXXXXXXXXXXXX/;x;}
   26115bp
   32198bp
   37256bp
   40001bp
   40023bp
   d
   :p
   g
' data_file

ก่อนอื่นเราจะทำการเว้นวรรคพื้นที่ที่มีรูปแบบที่ต้องการXXXXXXXXX แล้วจำไว้ว่าเฉพาะสำหรับหมายเลขบรรทัดที่ต้องการโดยการกระโดดไปที่ป้ายชื่อ: p ซึ่งจะดึงพื้นที่ค้างไว้ซึ่งจะถูกนำไปที่ stdout โดยปริยาย ไม่ใช่การจับคู่สายจะถูกลบ (เปลี่ยนdไปbถ้าคุณต้องการที่จะให้พวกเขา)


1

เนื่องจากการแทนที่นั้นเป็นแบบสแตติกและเนื่องจากการดำเนินการของการแทนที่หลายบรรทัดนั้นง่ายดังนั้นจึงsedอาจสร้างsedสคริปต์ขนาดใหญ่หนึ่งสคริปต์เพื่อทำงาน

สมมติว่าคุณมีหมายเลขบรรทัดในไฟล์แยกต่างหากlinenos.txtหมายเลขหนึ่งบรรทัดต่อบรรทัดจากนั้นเราสามารถสร้างsedสคริปต์(GNU) ผ่าน

$ awk '{ printf("%dc XXXXXXXXXXXXXXX\n", $0) }' linenos.txt >script.sed

หรือ

$ awk '{ print $0, "c XXXXXXXXXXXXXXX" }' linenos.txt >script.sed

จากนั้นเป็นเรื่องของการนำไปใช้กับไฟล์:

$ sed -f script.sed file >file.new

หมายเหตุ: ฉันไม่เคยเรียกใช้sedสคริปต์ที่มีขนาดใหญ่มากดังนั้นฉันจึงไม่รู้ว่า GNU sedจัดการกับประสิทธิภาพได้อย่างไร

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