วิกิพีเดีย:การเข้ารหัสเทมเพลตขั้นสูง

จากวิกิพีเดีย สารานุกรมเสรี
ข้ามไปที่การนำทาง ข้ามไปที่การค้นหา

มีบางอย่างที่เป็นแม่แบบขั้นสูงการเข้ารหัสเทคนิคในการปรับปรุงการแสดงผลหรือแก้ไขของแม่แบบในวิกิพีเดีย นอกจากนี้ยังมีกลยุทธ์บางอย่างสำหรับการแก้จุดบกพร่องพารามิเตอร์แม่แบบในมีเดียวิกิ ภาษามาร์กอัป หากเป็นไปได้ ควรใช้โมดูล lua

ข้อบกพร่องหลายอย่างเกี่ยวข้องกับความยากลำบากในการจัดการกับคุณลักษณะที่น่าอึดอัดใจในภาษามาร์กอัปซึ่งนำไปสู่ข้อผิดพลาดในการเขียนโค้ด อักขระเมตาที่ไม่สมดุลเป็นสาเหตุสำคัญของข้อผิดพลาด ตัวอย่างเช่น การเขียนโค้ด{{1}}}แทนที่จะ{{{1}}}ทำให้ทำงานเหมือนกับว่าเป็น{{1}} }ดังนั้นจึงเรียกใช้ Template:1 + "}"

การจัดรูปแบบวิกิของเนื้อหาของพารามิเตอร์มีความแตกต่างบางประการเมื่ออยู่ภายใน #if-expressions แต่ไม่ใช่เมื่ออยู่ภายนอก เทมเพลตที่ต้องเปลี่ยนต้องมีการจัดการพิเศษ การระบุค่าเริ่มต้นของพารามิเตอร์หรือนามแฝงของพารามิเตอร์จะครอบคลุมด้วยเช่นกัน

ระดับการทำรังจำกัดอยู่ที่40

ภายในแม่แบบเดียวขีด จำกัด การทำรังเป็น 40 สำนวนที่ซ้อนกันเช่น 40 หลาย"ถ้า-แล้วอื่นถ้า ..." ที่ 41 ซ้อนกัน "ถ้า" คำหลักข้อผิดพลาดข้อความอาจปรากฏเป็น: "เกินขีด จำกัด รัง" อย่างไรก็ตาม เมื่อไม่ได้ซ้อนกันเกิน 40 ระดับ เทมเพลตสามารถมี if-expressions และ switch-branches ได้หลายร้อยรายการ แต่ไม่สามารถซ้อนอยู่ภายในส่วนอื่นๆ ได้ทั้งหมด

เทมเพลตบางแบบมีการคำนวณแบบมีเงื่อนไขที่ซับซ้อนซึ่งซ้อนกันลึกกว่า 23 ระดับเป็นเวลาหลายปี นอกจากนี้แม่บางคนได้มีอยู่หลายร้อยถ้าแสดงออกสำหรับปีเพียงไม่ซ้อนกันทั้งหมดเป็นหนึ่งในยักษ์ใหญ่: ถ้า-แล้วอื่น-อื่น-อื่น-อื่น-อื่น ...

วิกิมีเดียวิกิจัดรูปแบบอนุประโยคภายใน #if

ปัญหาที่ทำให้การประมวลผลเทมเพลตซับซ้อนสำหรับพารามิเตอร์คือการจัดรูปแบบวิกิของเนื้อหาพารามิเตอร์เมื่ออยู่ภายใน if-logic (เช่น #if หรือ #ifeq) หรือ #switch (หรือ lc:, lcfirst:, uc:, ucfirst:) . ตั้งแต่เดือนพฤษภาคม 2012 โปรแกรมแยกวิเคราะห์มาร์กอัปมีเดียวิกิยังคงจัดรูปแบบเนื้อหาของพารามิเตอร์ในวิกิเมื่ออยู่ภายใน #if-expressions (แต่ไม่ใช่ภายนอก) ซึ่งหมายความว่าพารามิเตอร์ที่มีการเว้นวรรค อัฒภาคนำ ทวิภาค ( ตัวอย่างเช่น พารามิเตอร์{{{4}}}เมื่ออยู่นอก #if สามารถแสดงต่างจากภายใน{{#ifeq:{{{1}}}=0|{{{4}}} ...} }. สิ่งที่น่าตกใจที่สุดคือเมื่อพารามิเตอร์ 4 มีเครื่องหมายอัฒภาคนำหน้า ซึ่งทริกเกอร์การจัดรูปแบบให้กลายเป็นบรรทัดส่วนหัวเซมิโคลอนที่เป็นตัวหนา ye-olde :

การทดสอบ 1: {{#if:{{{4|}}}|{{{4|;}}} <== ใช่ อัฒภาค|ไม่ 4=ว่างเปล่า}}
การทดสอบ 2: {{#if:{{{4|;}}}|{{{4|;}}} <== ใช่ อัฒภาค|ไม่ 4=ว่าง}}
การทดสอบ 1: ไม่ 4=ว่างเปล่า
ทดสอบ 2:
<== ใช่ อัฒภาค
<== แยกตัวอย่างเซมิโคลอนส่วนหัว

ปัญหาเกิดขึ้นไม่ว่าจะอยู่ในนิพจน์มาร์กอัป #if, #ifexpr, #ifeq หรือ #switch หากพารามิเตอร์นำหน้าด้วยข้อความ ในส่วนคำสั่ง then/else ใดๆ การจัดรูปแบบวิกิภายในพารามิเตอร์จะไม่เกิดขึ้น

การทดสอบ 3: {{#ifexpr:{{{1|7}}}=7|<b></b>{{{4|;}}} เท่ากับ 7|ไม่ใช่ 7}}
การทดสอบ 4: {{#ifexpr:{{{1|7}}} < 9|{{4|#}}} น้อยกว่า 9|ไม่<9}}
การทดสอบ 5: {{#ifexpr:{{{1|7}}} < 9| {{{4|#}}} น้อยกว่า 9|ไม่<9}}
การทดสอบ 6: "{{#ifexpr:{{{1|7}}} < 9| {{{4|#}}} น้อยกว่า 9|ไม่<9}}"
ทดสอบ 3: ; เท่ากับ7
ทดสอบ 4:
  1. น้อยกว่า 9
การทดสอบ 5: # น้อยกว่า 9
การทดสอบ 6: " # น้อยกว่า 9"

ในการทดสอบที่ 4 เครื่องหมายปอนด์นำ "#" ทริกเกอร์การกำหนดหมายเลขอัตโนมัติของบรรทัด (เยื้องด้วย "1") สถานการณ์ของการมีเครื่องหมายอัฒภาค ทวิภาค หรือ "#" นำหน้าอาจพบได้ยากนัก แต่นี่เป็นเพียงการเตือน: สำหรับการแสดงเนื้อหาที่แท้จริงของพารามิเตอร์เทมเพลต ให้พยายามแสดงพารามิเตอร์นอกจุดเริ่มต้นของคำสั่ง if-statement หรือแสดงข้อความอื่นก่อนพารามิเตอร์ภายใน if-logic หรือเตรียมรับผลลัพธ์ที่น่าตกใจเมื่อพารามิเตอร์ถูกจัดรูปแบบ wiki เพื่อแสดงภายใน if-logic

หากผลลัพธ์ของ #if ฯลฯ ไม่ได้มีวัตถุประสงค์เพื่อจัดรูปแบบ ให้ใช้# , : , และ; แทน# , : , และ; จะทำงานได้ดี

การทดสอบ 7: {{#ifexpr:{{{1|7}}} < 9|{{4|#}}} น้อยกว่า 9|ไม่<9}}
การทดสอบ 7: # น้อยกว่า 9

แก้จุดบกพร่อง

ข้อผิดพลาดในการเขียนโค้ดจำนวนมากสามารถดีบักได้ง่ายขึ้น โดยพยายามแยกส่วนของโค้ดที่ข้อผิดพลาดในการเขียนโปรแกรมเกิดขึ้นได้มากที่สุด การพิสูจน์อักษรอย่างเข้มข้นของโฟลว์ลอจิกมักเป็นวิธีแก้ไขที่เร็วที่สุด เช่น การตรวจสอบข้อผิดพลาดทางไวยากรณ์ทั่วไป (ดูด้านล่าง: "ข้อผิดพลาดในการเข้ารหัสทั่วไป" ) บางครั้ง ส่วนของโค้ดที่มีปัญหาสามารถคัดลอกลงในหน้าทดสอบสั้นๆ ได้ จากนั้นให้ทดสอบโดยแก้ไข-แสดงตัวอย่าง แยกกัน อย่างไรก็ตาม หากการแก้ไขหน้าต่างหน้าพิเศษนั้นดูเหมือนใช้ความพยายามมากเกินไป ให้ลองคัดลอกโค้ดไปที่ด้านบนสุดของเทมเพลตปัจจุบัน ในทำนองเดียวกัน เทมเพลตสามารถพัฒนาได้ในระยะแรก โดยมีหลายส่วนของโค้ด แต่ละส่วนจะถูกดีบั๊กแยกกัน จากนั้นจึงรวมเข้าด้วยกันในที่สุด เช่น ส่วนที่ซ้อนกันด้วย if-then-else-if

ในการทบทวนตัวเลือกเหล่านั้น ให้พิจารณา:

  • ลองตรวจทานโค้ดที่มีปัญหาอย่างระมัดระวัง โดยจับคู่ "{{" กับ "}}" (ลองใช้ตัวเน้นไวยากรณ์ของ EquazcionสำหรับNotepad++ )
  • คัดลอกส่วนเทมเพลตลงในหน้าต่างแก้ไขหน้าทดสอบเพื่อแก้ไขข้อบกพร่อง
  • คัดลอกส่วนเทมเพลตไปที่ด้านบนของเทมเพลตเพื่อแก้ไขข้อบกพร่อง
  • ปรับโครงสร้างเทมเพลตใหม่เพื่อให้แต่ละส่วนแยกจากกันมากขึ้น

กลยุทธ์พื้นฐาน: แยกส่วนโค้ดที่จะดีบั๊ก

ขั้นต่อไป การทดสอบในแต่ละส่วนของโค้ดเป็นสิ่งสำคัญ มีสุภาษิตโบราณบางคำที่ควรคำนึงถึง:

อาจใส่ตัวอย่างต่างๆ ในหน้าย่อยเอกสารของแต่ละเทมเพลต เพื่อช่วยตรวจหาปัญหาในระยะเริ่มต้นของการพัฒนา อย่างไรก็ตาม สำหรับเทมเพลตที่ซับซ้อน หน้าพูดคุยหรือหน้าย่อยพิเศษ "/testcases" ควรมีส่วนของตัวอย่างจำนวนมาก (จำนวนมาก) เพื่อแสดงขอบเขตทั้งหมดของคุณลักษณะเทมเพลต

พารามิเตอร์เริ่มต้นในนิพจน์และ if-logic

เมื่อพัฒนาส่วนของมาร์กอัปที่ใช้พารามิเตอร์เทมเพลต ให้พยายามตั้งค่าพารามิเตอร์แต่ละรายการด้วยค่าเริ่มต้นเสมอ โดยเฉพาะอย่างยิ่งภายในนิพจน์หรือการเข้ารหัสแบบ if-logic:

  • {{#expr: 109.75 / {{{1|1}}} }} → ค่าเริ่มต้น {1} เป็น 1 ไม่ใช่ศูนย์
  • {{#ifeq: {{{answer|y}}}|y|show yes}}

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

หากพารามิเตอร์เหล่านั้นไม่ได้รับค่าเริ่มต้น ส่วนของโค้ดเหล่านั้นจะไม่สามารถทดสอบได้ ระหว่างแก้ไข-ดูตัวอย่าง ขณะแก้ไขเทมเพลต พารามิเตอร์ใดๆ ที่ไม่มีค่าเริ่มต้นจะกลายเป็นข้อความวงเล็บปีกกาสามตัวตามตัวอักษร (เช่น อักขระตามตัวอักษร 7 ตัว: ) และพารามิเตอร์ที่ไม่ใช่ค่าเริ่มต้นจะไม่สามารถประเมินได้ ในนิพจน์หรือ if-logic ในระหว่างการดูตัวอย่างการแก้ไขของหน้าเทมเพลต {{{x}}}

ข้อผิดพลาดในการเข้ารหัสทั่วไป

มีข้อผิดพลาดในการเข้ารหัสทั่วไปหลายประการซึ่งจะสร้างปัญหาในการประมวลผลเทมเพลต ข้อมูลต่อไปนี้สามารถใช้เป็นรายการตรวจสอบ เพื่อช่วยดีบักปัญหา เมื่อเทมเพลตดูเหมือนจะทำงานผิดปกติ:

  • วงเล็บปิดน้อยเกินไป:ปัญหาทั่วไปคือใส่วงเล็บปิดเพียง 2 อันรอบหมายเลขพารามิเตอร์หรือชื่อ เช่น. การมีเพียง 2 วงเล็บปิดอาจถือว่าพารามิเตอร์เป็นเทมเพลตชื่อ "Template:1" (นำหน้าด้วยวงเล็บปีกกา "{"){{{1}}}}
  • ความคิดเห็นที่ยังไม่ได้เปิด: การลืมแทรก<!--ที่จุดเริ่มต้นของความคิดเห็น HTML อาจทำให้เกิดผลลัพธ์ที่แปลกประหลาด โดยไม่มีข้อความแสดงข้อผิดพลาด การลืมเครื่องหมายอัศเจรีย์เป็นเรื่องธรรมดามากควรเป็น.<--<!--
  • ความคิดเห็นที่ไม่เปิดเผย: การลืมใส่-->ที่ส่วนท้ายของความคิดเห็น HTML อาจทำให้เกิดผลลัพธ์ที่แปลกประหลาด โดยไม่มีข้อความแสดงข้อผิดพลาด
  • การละเว้นเครื่องหมายทวิภาคหรือ "#" บน "#ifexpr": การลืมใส่ "#" หรือโคลอนสำหรับ "#ifexpr:" หรือ "#expr:" อาจให้ผลลัพธ์ที่แปลกประหลาด เมื่อส่งต่อไปยังเทมเพลตย่อยอื่นๆ
การละเว้นโคลอนจะกลายเป็นข้อความตามตัวอักษร: {{#ifexpr {{{1|y}}}=0|then zero|else not}}

โปรดทราบว่าข้อผิดพลาดในการเข้ารหัสทั่วไปเหล่านี้สามารถตรวจพบได้ง่ายโดยตัวตรวจสอบไวยากรณ์อย่างง่าย เช่น การเตือนว่าวงเล็บปีกกา 3&2 อาจมีปัญหา: จะถือว่าเป็น "{Template:Size" ที่พยายามส่ง 180px เป็นพารามิเตอร์เนื่องจากมีเพียง 2 วงเล็บปีกกา . {{{size|180px}}

อีกครั้ง ให้ตรวจสอบข้อผิดพลาดทั่วไปก่อนเสมอ เนื่องจากเป็นขั้นตอนแรก สามารถหลีกเลี่ยงเวลาในการค้นหา "ข้อผิดพลาดที่ซับซ้อน" ซึ่งไม่เคยมีอยู่จริงได้ ข้อควรจำ: ภาษามาร์กอัปมีเดียวิกิมีแนวโน้มที่จะเกิดข้อผิดพลาดได้ง่ายมาก นั่นคือสาเหตุที่ข้อผิดพลาดในการเขียนโค้ดเกิดขึ้นมากมาย และนั่นเป็นสาเหตุ:

พิจารณาข้างต้นเป็นรายการตรวจสอบเพื่อลองก่อน เป็นประเภทของการตรวจสุขภาพจิตสำหรับแม่แบบ

ปัญหาที่น่าสยดสยองมากมายเป็นเพียงการแก้ไขไวยากรณ์เพียง 1 นาทีเท่านั้น

การเข้ารหัสเทมเพลตเพื่ออนุญาตการแทนที่ WP:SUBST

ในบางกรณี เทมเพลตอาจจำเป็นต้องเขียนใหม่เพื่อให้สามารถแทนที่ข้อความได้ (ต่อWP:SUBST ) โดยที่ผลลัพธ์ของการรันเทมเพลตจะถูกบันทึกลงในเพจระหว่างการดำเนินการแก้ไข-SAVE ในกรณีนั้น ต้องแทรกคำนำหน้า safesubst ลงในทุกฟังก์ชันมาร์กอัปที่ใช้ภายในเทมเพลตนั้น ในทุกระดับของตรรกะที่ซ้อนกัน นอกจากนี้ทุกความคิดเห็น HTML จะต้องถูกล้อมรอบด้วยแท็ก "noinclude": [a]มิฉะนั้น ความคิดเห็น HTML ที่เรียกใช้ทั้งหมดจะถูกเก็บไว้ในเพจ SAVEd ตามลำดับที่เรียกใช้เทมเพลต หมายเหตุ: "noinclude" พิเศษทั้งหมดและ<noinclude><!--HTML comment HERE--></noinclude>"{{{|safesubst:}}}" คำหลักมีแนวโน้มว่าจะต้องมีการเยื้องมาร์กอัปของเทมเพลตภายในใหม่ เพื่อให้พอดีกับข้อความที่แทรกเพิ่มเติมทั้งหมด ซึ่งจะขยายและทำให้รูปแบบมาร์กอัปดั้งเดิมกว้างขึ้น

โดยเฉพาะอย่างยิ่ง หากต้องการแก้ไขเทมเพลตเพื่อให้สามารถแทนที่ข้อความได้ จะต้องแทรกคำนำหน้าลงในวงเล็บปีกกาคู่ที่เปิดอยู่ของฟังก์ชันมาร์กอัปแต่ละรายการภายในเทมเพลตนั้น ตัวอย่างของการแทรกคำนำหน้า safesubst ภายในมาร์กอัปของเทมเพลต: "{{{|safesubst:}}}""{{"

  • Total articles now: {{NUMBEROFARTICLES}} → 6,390,617
  • Total articles was: {{ subst:NUMBEROFARTICLES}} → 3,953,715
  • {{ {{{|safesubst:}}}#ifeq:{{{1|AX}}}|AX|yes}}
  • {{ {{{|safesubst:}}}lc:THIS LOWERCASE TEXT}} → ข้อความตัวพิมพ์เล็กนี้

โดยทั่วไป ทุกฟังก์ชันมาร์กอัปที่ขึ้นต้นด้วยเครื่องหมายปีกกาคู่ " {{" จะต้องมีการเปลี่ยนแปลงเพื่อแทรก safesubst-prefix แบบยาว " " (โดยไม่เว้นวรรคหลังจากนั้น) [b]การทำงานของคีย์เวิร์ด "safesubst" คือการอนุญาตให้มีการแทนที่แบบมีเงื่อนไขของมาร์กอัป เมื่อเทมเพลตทั้งหมดถูกเรียกใช้เป็น {{subst:MyTemplate|...}} โดยพื้นฐานแล้ว คีย์เวิร์ด "safesubst" อาจเรียกว่า "ifsubst" ตามความหมาย "ถ้าใช้ 'subst:' เพื่อเรียกใช้เทมเพลตนี้ ให้แทนที่ที่นี่ด้วย" {{{|safesubst:}}}

ข้อควรจำ: ต้องแทรกคำนำหน้า safesubst ลงในทุกฟังก์ชันมาร์กอัปภายในเทมเพลตนั้น ยกเว้นตรรกะการทดสอบที่ไม่เคยใช้ในเพจจริง มาร์กอัปใดๆ ที่ละเว้น "safesubst" จะล้มเหลวหากเทมเพลตถูกเรียกใช้งานโดยโหมดย่อย "{{subst:MyTemplate|...}}" พารามิเตอร์จะไม่เปลี่ยนแปลง ดังนั้นจึงไม่เปลี่ยนแปลง โดยไม่มี safesubst-prefix "{{{1}}}"

ข้อยกเว้น:เฉพาะตรรกะที่จะไม่ถูกเก็บไว้ในหน้าเว็บเท่านั้นที่สามารถละเว้น "safesubst" เช่น ตรรกะการทดสอบซึ่งถูกเรียกใช้โดยค่าพารามิเตอร์พิเศษที่ไม่เคยใช้ภายในหน้าที่เก็บไว้ มาร์กอัปใดๆ ที่ละเว้น "safesubst" จะทำงานเฉพาะในระหว่างการแยกปกติ แต่จะล้มเหลวหากเทมเพลตถูกเรียกใช้งานโดยใช้คำนำหน้าโหมดย่อย "subst:" สำหรับตัวอย่างเพิ่มเติมและคำอธิบายทางเทคนิคเพิ่มเติมโปรดดูที่: WP: ชดเชย

การเยื้องบรรทัดที่ยาว:ข้อความ safesubst-prefix ที่เพิ่มเข้ามาทั้งหมดจะทำให้บรรทัดกว้างขึ้น ดังนั้น เพื่อปรับปรุงความสามารถในการอ่าน จึงอาจแยกและเยื้องหลังเครื่องหมายปีกกาสามตัว" ในคำนำหน้าใดก็ได้ตัวอย่างเช่น "{{{""{{{|safesubst:}}}"

  • {{ {{{|safesubst:}}}#ifeq:{{ {{{
           |safesubst:}}}padleft:|1|{{{1}}} }}|A|Begins with "A"}}

ในรูปแบบการเยื้องนั้น ข้อความ "|safesubst:" จะเริ่มต้นบรรทัดถัดไป หลีกเลี่ยงการตัดบรรทัดหลังคำนำหน้าเนื่องจากฟังก์ชันมาร์กอัปหลายอย่างอาจทำงานไม่ถูกต้อง เว้นแต่จะแนบคำนำหน้า safesubst ก่อนคีย์เวิร์ดทันที เช่น"{{{|safesubst:}}}""{{&nbsp;{{{|safesubst:}}}#ifeq:...}}"

ตัวอย่างเทมเพลตขนาดใหญ่มาก

เมื่อพยายามดำเนินการที่ซับซ้อนมากขึ้นหรือซับซ้อน อาจมีความกลัวโดยสัญชาตญาณว่าเทมเพลตไม่สามารถมีขนาดใหญ่เท่าที่จำเป็น อย่างไรก็ตาม มีเทมเพลตขนาดใหญ่จำนวนมากที่ใช้งานบน Wikipedia มาหลายปีแล้ว ตัวอย่างเช่น:

ตัวจัดรูปแบบต้นฉบับเชิงอรรถเทมเพลต:Citation/coreแสดงรูปแบบการอ้างอิงที่เป็นมาตรฐาน ตามที่เรียกใช้โดยเทมเพลต wrapper หลายตัวซึ่งส่งผ่านพารามิเตอร์หลายร้อยตัว โดยที่ลอจิกหลักตรวจสอบค่าพารามิเตอร์ 621 ค่าในนิพจน์มาร์กอัปแบบมีเงื่อนไข

ลองเขียนโปรแกรมบ้าง

หน้าSpecial:ExpandTemplatesใช้ข้อความวิกิบางส่วนและขยายทุกอย่างในวงเล็บคู่แบบเรียกซ้ำ: เทมเพลตฟังก์ชัน parserเช่น {{#if:...}} และตัวแปร เช่น {{CURRENTDAY}}

ดูสิ่งนี้ด้วย

หมายเหตุ

  1. ^ แต่ถ้าคุณต้องการให้ความคิดเห็น HTML ปรากฏขึ้น อย่างในกรณี เช่น ด้วยเทมเพลตคำเตือนผู้ใช้อย่าใส่ความคิดเห็น HTML ไว้ใน<noinclude>แท็ก
  2. ^ หากคุณคุ้นเคยกับนิพจน์ทั่วไปคุณสามารถทำได้ดังนี้:
    • ค้นหารูปแบบ([^{]){{([^{])และแทนที่ด้วย\1{{ {{{|safesubst:}}}\2
    หรือในขั้นตอนเดียวสำหรับ regex หนึ่งสไตล์:
    • s/([^{]){{([^{])/\1{{ {{{|safesubst:}}}\2/g
    คุณอาจต้องแยกแถวยาว โปรดดูที่ "การเยื้องเส้นยาว" ในส่วนนี้ ในทางปฏิบัติ มันง่ายกว่าที่จะรวมบรรทัดของโค้ดแทนที่จะแยกบรรทัด ดังนั้นหากคุณแทนที่ช่องว่างในรูปแบบแทนที่ด้านบนด้วยการขึ้นบรรทัดใหม่ (พร้อมตัวเลือกช่องว่างสีขาว) แทน มันจะทำลายบรรทัดด้วยการแทนที่ทุกครั้ง เมื่อเสร็จแล้วให้กลับไปเข้าร่วมบรรทัดที่สั้นเกินไป