ฉันมีไฟล์ XML ขนาดใหญ่
<obj param="2542">
<obj param="2333">
<obj param="6433">
ฉันต้องการเพิ่มค่า "param" ทั้งหมดด้วยจำนวนหนึ่ง ฉันสามารถจับคู่ตัวเลขที่ฉันต้องการด้วยการค้นหา regexp ในตัวแก้ไขหลายตัว แต่จะนำคณิตศาสตร์ไปใช้กับการแทนที่ได้อย่างไร
ฉันมีไฟล์ XML ขนาดใหญ่
<obj param="2542">
<obj param="2333">
<obj param="6433">
ฉันต้องการเพิ่มค่า "param" ทั้งหมดด้วยจำนวนหนึ่ง ฉันสามารถจับคู่ตัวเลขที่ฉันต้องการด้วยการค้นหา regexp ในตัวแก้ไขหลายตัว แต่จะนำคณิตศาสตร์ไปใช้กับการแทนที่ได้อย่างไร
คำตอบ:
หลังจากพูดอีกนิดหน่อยมันกลับกลายเป็นกลุ่มที่สามารถทำได้ด้วยคำสั่งเดียว ตัวอย่างเช่นหากต้องการเพิ่ม 50 ไปยังหมายเลขทั้งหมดที่<obj param="คุณสามารถใช้ได้
:%s@<obj param="\(\d\+\)@\='<obj param="' . (submatch(1) + 50)@g
ขอผมทำลายมันลง
: เป็นวิธีทั่วไปในการเข้าสู่ / ระบุโหมดบรรทัดคำสั่งในกลุ่ม
%หมายความว่าภายในขอบเขตของเอกสารทั้งหมด คุณสามารถใส่ช่วงตัวเลขเช่น1,50เพื่อทำภายใน 50 บรรทัดแรกแทน
s เป็นชวเลขสำหรับทดแทน (คุณสามารถเขียนคำทั้งหมดถ้าคุณต้องการ)
@เป็นตัวคั่น คุณสามารถใช้ตัวละครอื่น ๆ ตราบใดที่มันไม่ได้อยู่ในสิ่งที่คุณค้นหา แค่ใช้มันสามครั้ง (ไวยากรณ์คล้ายกับsed)
ทุกอย่างที่เกิดขึ้นต่อไปของตัวคั่น @ เป็นรูปแบบ reg ex เพื่อค้นหาในกรณีนี้<obj param="ตามด้วย\d\+ซึ่งเป็นจำนวนหลักใด ๆ \(และ\)จะมีการตั้งค่านี้ลำดับทั้งหมดของตัวเลขที่เป็นกลุ่มอดีต reg เดียวที่จะตรงกับ backreferences เหมือน\1หรือเป็นกลุ่มของsubmatchคำสั่ง
จากนั้นตัวคั่นจะ@ทำเครื่องหมายว่าสิ่งที่ตามมาเป็นข้อความแทนที่
\=ที่หมายถึงการเริ่มต้นที่นี่เพื่อทดแทนผลของการแสดงออกการประเมินมากกว่ารูปแบบ reg อดีตหรือสตริงซึ่งเป็นกุญแจสำคัญที่นี่
จากนั้นเรามี'<obj param="'ข้อความเริ่มต้นสำหรับการแทนที่ .ซึ่งต่อไปนี้เป็นฟังก์ชั่นที่เป็นกลุ่มสำหรับการเชื่อมโยงสาย
submatch(1)เป็นเสียงเรียกเข้าในตัวฟังก์ชั่นที่สามารถใช้เฉพาะภายในคำสั่งเปลี่ยนตัวและกลับสตริงซึ่งเป็นเช่นเดียวกับ regex ไม่\1; คุณจะใช้submatch(2)สำหรับเทียบเท่าของ regex \2และอื่น ๆ ( \0เป็นรูปแบบการจับคู่ทั้งหมด แต่เราไม่ต้องการที่นี่.) The \(และในรูปแบบการค้นหาที่มีการใช้ในการทำเครื่องหมายปิดสิ่งที่นับเป็น\)submatch(1)
ดังนั้น(submatch(1) + 50)ให้ผลลัพธ์ของการเพิ่ม 50 จำนวนตัวเลขที่ตามมา<obj param="ในรูปแบบรูปแบบการค้นหา
ตัวคั่น@จะใช้อีกครั้งเพื่อทำเครื่องหมายปิดท้ายข้อความการแทนที่
การตั้งค่าสถานะgถูกใช้เพื่อทำให้การแทนที่เป็นแบบโกลบอล คุณสามารถละเว้นสิ่งนี้ได้หากคุณต้องการแทนที่อินสแตนซ์แรกในแต่ละบรรทัดเท่านั้น
คุณสามารถหาวิธีเพิ่มจำนวนที่แตกต่างกันหรือลบหรือหารเป็นต้น
ใน Emacs (ตั้งแต่รุ่น 23): ใช้\,ในการดำเนินการโดยพลการรหัสเสียงกระเพื่อมในการเปลี่ยน regexp ตัวอย่างเช่นหากต้องการยกกำลังสองตัวเลขที่คุณสามารถใช้ได้
M-x replace-regexp
param="\([0-9]+\)"
param="\,(* \#1 \#1)"
ใน Vim: เริ่มข้อความแทนที่ของคุณด้วย\=(ดู:help sub-replace-special) ตัวอย่างเช่นเมื่อต้องการยกกำลังสองตัวเลข:
s!param="\([0-9]\+\)"!\='param="'.submatch(1)*submatch(1).'"'!
บรรณาธิการหลายคนอนุญาตให้คุณทำสิ่งนี้ด้วยแมโคร: กำหนดมาโครที่ 1. ค้นหาการจับคู่ถัดไปและ 2. ทำการแทนที่ (ใช้เครื่องมือภายนอกสำหรับการคำนวณทางคณิตศาสตร์หากจำเป็น); ทำซ้ำแมโครหลาย ๆ ครั้งตามที่คุณมีการแข่งขัน
คุณสามารถใช้เสียงเรียกเข้าเพื่อทำสิ่งนั้นเพื่อคุณ เพียงแค่เปิดไฟล์ของคุณและบันทึกแมโคร ตัวอย่าง: ค้นหาหมายเลขใด ๆ
/[0-9]{1,}
จากนั้นกด q และ a (เก็บแมโครในการลงทะเบียน a) หลังจากนั้นกด Ctrl-X (เพิ่มหมายเลข 1) แล้วกด n (สำหรับผลการค้นหาถัดไป) หลังจากนั้น หลังจากคุณทำเสร็จแล้วให้กด q อีกครั้งเพื่อบันทึกแมโคร ตอนนี้คุณสามารถใช้แมโครกับหมายเลขถัดไปได้โดยกด @ + a นี่จะเปลี่ยนหมายเลขปัจจุบันและข้ามไปยังหมายเลขถัดไป ด้วยการทำซ้ำหรือใช้ x @ a คุณสามารถทำซ้ำ x ได้
คำอธิบายนั้นอาจไม่เพียงพอที่จะแสดงว่าสามารถทำได้ เพียงอ้างถึงบทช่วยสอนที่อธิบายกลไกแมโครในกลุ่ม
vimและemacsสามารถทำสิ่งนี้ได้ แต่อาจต้องเขียนสคริปต์แทนที่จะใช้คำสั่งเดียว