เครื่องมือแก้ไขข้อความใด ๆ ที่สามารถใช้คณิตศาสตร์เพื่อแทนที่ข้อความได้


15

ฉันมีไฟล์ XML ขนาดใหญ่

<obj param="2542">
<obj param="2333">
<obj param="6433">

ฉันต้องการเพิ่มค่า "param" ทั้งหมดด้วยจำนวนหนึ่ง ฉันสามารถจับคู่ตัวเลขที่ฉันต้องการด้วยการค้นหา regexp ในตัวแก้ไขหลายตัว แต่จะนำคณิตศาสตร์ไปใช้กับการแทนที่ได้อย่างไร


1
ระบบปฏิบัติการอะไร คุณจะมีความสุขกับเชลล์สคริปต์แทน (ซึ่งจะค่อนข้างง่าย) อย่างไรก็ตามฉันแน่ใจvimและemacsสามารถทำสิ่งนี้ได้ แต่อาจต้องเขียนสคริปต์แทนที่จะใช้คำสั่งเดียว
frabjous

@ frabjous ภายใต้ windows ฉันจะไม่เขียนอะไรถ้าเป็นไปได้ แต่ถ้าคุณโพสต์เชลล์สคริปต์ผมมั่นใจว่ามันจะมีประโยชน์สำหรับคนจำนวนมาก
serg

คำตอบ:


18

หลังจากพูดอีกนิดหน่อยมันกลับกลายเป็นกลุ่มที่สามารถทำได้ด้วยคำสั่งเดียว ตัวอย่างเช่นหากต้องการเพิ่ม 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ถูกใช้เพื่อทำให้การแทนที่เป็นแบบโกลบอล คุณสามารถละเว้นสิ่งนี้ได้หากคุณต้องการแทนที่อินสแตนซ์แรกในแต่ละบรรทัดเท่านั้น

คุณสามารถหาวิธีเพิ่มจำนวนที่แตกต่างกันหรือลบหรือหารเป็นต้น


นี่เยี่ยมมากฉันมีไฟล์ GPX ที่เสียหายเพราะค่าลองจิจูดนั้นไม่ถูกต้องอย่างสมบูรณ์ โชคดีละติจูดก็โอเคดังนั้นการใช้แผนที่ฉันสามารถหาค่าที่ถูกต้องอันดับแรกควรทำคณิตศาสตร์และหาว่าฉันต้องลบ 4294.567548 จากแต่ละค่าเพื่อให้ถูกต้อง บล็อกที่สะดุดเพียงอย่างเดียวที่ฉันมีคือวิธีนี้ใช้ไม่ได้กับจำนวนจุดลอยตัวดังนั้นฉันจึงทำแต่ละจุดทศนิยมเป็นการแทนที่แบบแยกส่วนหนึ่ง -4294 และหนึ่ง -567548
stuffe

7

ใน 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. ทำการแทนที่ (ใช้เครื่องมือภายนอกสำหรับการคำนวณทางคณิตศาสตร์หากจำเป็น); ทำซ้ำแมโครหลาย ๆ ครั้งตามที่คุณมีการแข่งขัน


คำตอบที่ไม่ถูกต้อง สั้นและคุณครอบคลุม 2 บรรณาธิการ + กรณีทั่วไป
derekv

1

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

/[0-9]{1,}

จากนั้นกด q และ a (เก็บแมโครในการลงทะเบียน a) หลังจากนั้นกด Ctrl-X (เพิ่มหมายเลข 1) แล้วกด n (สำหรับผลการค้นหาถัดไป) หลังจากนั้น หลังจากคุณทำเสร็จแล้วให้กด q อีกครั้งเพื่อบันทึกแมโคร ตอนนี้คุณสามารถใช้แมโครกับหมายเลขถัดไปได้โดยกด @ + a นี่จะเปลี่ยนหมายเลขปัจจุบันและข้ามไปยังหมายเลขถัดไป ด้วยการทำซ้ำหรือใช้ x @ a คุณสามารถทำซ้ำ x ได้

คำอธิบายนั้นอาจไม่เพียงพอที่จะแสดงว่าสามารถทำได้ เพียงอ้างถึงบทช่วยสอนที่อธิบายกลไกแมโครในกลุ่ม


ถ้าฉันต้องการเปลี่ยนหมายเลขไม่ใช่ 1 แต่เป็นล้าน หรืออาจใช้การคูณ / การหารบ้าง
serg

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