ฉันจะทำให้การแข่งขันไม่ใช่ความโลภเป็นกลุ่มได้อย่างไร?


479

ฉันมีไฟล์ HTML ขนาดใหญ่ที่มีมาร์กอัปมากมายซึ่งมีลักษณะดังนี้:

<p class="MsoNormal" style="margin: 0in 0in 0pt;">
  <span style="font-size: small; font-family: Times New Roman;">stuff here</span>
</p>

ฉันกำลังพยายามค้นหาและแทนที่เป็นกลุ่มเพื่อกำจัดทุกอย่างclass=""และstyle=""แต่ฉันมีปัญหาในการทำให้การแข่งขันไม่ดี

ความพยายามครั้งแรกของฉันคือสิ่งนี้

%s/style=".*?"//g

แต่เสียงเรียกเข้าไม่เหมือน?กัน น่าเสียดายที่การลบ?ทำให้การแข่งขันโลภเกินไป

ฉันจะทำให้การจับคู่ของฉันไม่มีความสุขได้อย่างไร


ฉันคิดว่าคำตอบของพอลนั้นดี แค่พูดอย่างนั้น "?" ไม่ได้หมายความว่าเป็นตัวเลือกในกลุ่ม (ถ้านี่คือสิ่งที่คุณต้องการให้บรรลุโดยใช้ "?")
LB40

14
@LB ในหลายภาษา,. *? หมายถึงการจับคู่ตัวละครใด ๆ แต่จะไม่โลภ นั่นคือสิ่งที่เขาพยายามที่จะบรรลุ
แรนดี้มอร์ริส

คำตอบ:


734

แทนการใช้งาน.*.\{-}

%s/style=".\{-}"//g

นอกจากนี้ดู :help non-greedy


37
ไม่เข้าใจง่ายมากนี่เป็นสิ่งที่กลุ่มเสียงเรียกเข้าทำเท่านั้น
Ehtesh Choudhury

94
ทุกอย่างมีภาษานิพจน์ปกติของตัวเอง ... ซึ่งเป็นหนึ่งในปัญหาที่ใหญ่ที่สุดของ regex
Patrick Farrell

35
เครื่องมือเหล่านี้จำนวนมากครบกำหนดในเวลาเดียวกันและพัฒนาภาษาของตนเองในภาษานิพจน์ปกติอย่างอิสระ เครื่องมือเหล่านี้จำนวนมากกำลังพยายามแก้ไขปัญหาที่แตกต่างกันดังนั้นจึงสมเหตุสมผลว่าไวยากรณ์อาจแตกต่างกันอย่างสิ้นเชิงระหว่างการใช้งานเหล่านี้ เราต้องยอมรับว่านี่เป็นเพียงวิธีการทำงานของโลกแห่งความจริงแม้ว่าบางครั้งมันทำให้ชีวิตของเรายากขึ้นในฐานะนักพัฒนา โชคดีที่มีเครื่องมืออย่างน้อยให้การใช้งาน regex ที่เข้ากันได้กับ Perl ในปัจจุบันนี้ น่าเสียดายที่ Vim ไม่ใช่หนึ่งในนั้น
แรนดี้มอร์ริส

15
ถ้าใครชอบค่าเริ่มต้นค้นหาของพวกเขากับตัวเอง\v(ธงวิเศษมาก) .{-}คุณจะต้องการใช้งาน
jgillman

48
@Shurane @Ziggy Mnemonic: ควบคุมจำนวนการทำซ้ำเช่นเดียวกับ{1,3}(วงเล็บปีกกา) เครื่องหมายลบ-หมายถึง: ทำซ้ำให้น้อยที่สุด (น้อย == ลบ);)
Ciro Santilli 法轮功冠状病病六四事件法轮功



17

หากคุณสะดวกกว่าไวยากรณ์ PCRE regex ซึ่ง

  1. สนับสนุนผู้ประกอบการที่ไม่โลภ? ตามที่คุณถามใน OP; และ
  2. ไม่ต้องการ backwhacking การจัดกลุ่มและผู้ประกอบการ cardinality (ความต้องการไวยากรณ์เสียงเรียกเข้าที่ใช้งานง่ายที่สุดเนื่องจากคุณไม่ได้จับคู่อักขระตามตัวอักษร แต่ระบุผู้ให้บริการ) และ
  3. คุณมี [g] เสียงเรียกเข้าที่คอมไพล์ด้วยคุณลักษณะ Perl ทดสอบการใช้งาน

    : ver และตรวจสอบคุณสมบัติ; ถ้ามี + perl คุณก็ไปได้ดี)

ลองค้นหา / แทนที่โดยใช้

:perldo s///

ตัวอย่าง. สลับ src และแอตทริบิวต์ alt ในแท็ก img:

<p class="logo"><a href="/"><img src="/caminoglobal_en/includes/themes/camino/images/header_logo.png" alt=""></a></p>

:perldo s/(src=".*?")\s+(alt=".*?")/$2 $1/

<p class="logo"><a href="/"><img alt="" src="/caminoglobal_en/includes/themes/camino/images/header_logo.png"></a></p>

1
perldoใช้งานได้ดี แต่น่าเสียดายที่ไม่เน้นการทดสอบที่เลือกขณะพิมพ์ regex
mljrg

12

ฉันพบว่าวิธีแก้ปัญหาที่ดีสำหรับคำถามประเภทนี้คือ:

:%! sed ...

(หรือ Perl ถ้าคุณต้องการ) IOW แทนที่จะใช้การเรียนรู้ลักษณะเฉพาะของ regim ที่เป็นกลุ่มใช้เครื่องมือที่คุณรู้อยู่แล้ว การใช้ Perl จะทำให้ ตัวดัดแปลงทำงานเพื่อเลิกการจับคู่


2
จุดดี แต่ความสามารถใน/patternการตรวจสอบว่าคุณจับคู่รูปแบบอย่างถูกต้องก่อนที่จะนำไปใช้และการใช้โมดิcฟายเออร์ในนิพจน์ปกติของคุณนั้นก็ดี :)
João Portela

สิ่งนี้ถูกต้อง การแก้ปัญหาทั้งหมดที่นี่ไม่ได้อยู่ใกล้กับความโลภ! หากคุณต้องจับคู่ [0-9] \ {7} ในบรรทัดที่มีข้อความจำนวนมากและเกิดขึ้นหลายครั้งของรูปแบบนั้นจะไม่มีวิธีแก้ปัญหาที่นี่ การแก้ปัญหาที่นี่ทำงานได้กับสิ่งง่าย ๆ เท่านั้น (ซึ่งจะยุติธรรมคือสิ่งที่ถูกถาม) แต่ถ้าคุณทำมากกว่าการค้นหาจนถึงใบเสนอราคาถัดไปเสียงเรียกเข้าจะไม่ช่วย
gcb


2

Plugin eregex.vimจัดการกับตัวดำเนินการที่ไม่ใช่โลภแบบ Perl *?และ+?


@xsilenT github.com/othree/eregex.vim : "ขอแนะนำให้ติดตั้งสคริปต์โดยใช้ Vundle หรือเชื้อโรค"
exe

ขอโทษที่ฉันไม่รู้วิธีใช้ Vundle หรือเชื้อโรค
xsilen T

-4

G'day,

การประมวลผล regexp ของ Vim ไม่ได้ยอดเยี่ยมเกินไป ฉันพบว่าไวยากรณ์ regexp สำหรับ sed เป็นเรื่องเกี่ยวกับการจับคู่ที่เหมาะสมสำหรับความสามารถของกลุ่ม

ฉันมักจะตั้งเน้นการค้นหาใน (: set hlsearch) แล้วเล่นกับ regexp หลังจากเข้าสู่เครื่องหมายทับเพื่อเข้าสู่โหมดการค้นหา

แก้ไข:ทำเครื่องหมายเคล็ดลับในการลดการจับคู่โลภนั้นรวมอยู่ในหนังสือยอดเยี่ยม "Dale Dougherty" Sed & Awk "( ลิงก์ Amazon ที่ถูกสุขอนามัย )

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

HTH

เสียงเชียร์


7
การประมวลผล regex ของ Vim นั้นค่อนข้างดีทีเดียว มันสามารถทำสิ่งต่าง ๆ ที่ไม่สามารถทำได้เช่นจับคู่หมายเลขบรรทัด / คอลัมน์หรือการจับคู่โดยยึดตามการจำแนกประเภทของอักขระเป็นคำหลักหรือตัวระบุหรือช่องว่าง นอกจากนี้ยังมีการยืนยันความกว้างเป็นศูนย์และความสามารถในการใส่นิพจน์ทางด้านขวาของการแทนที่ ถ้าคุณใช้\vมันจะช่วยให้ไวยากรณ์สะอาดขึ้นมาก
Brian Carper

1
@Brian, ไชโย ฉันจะช่วย regex และดูสิ่งที่ฉันหายไป
Rob Wells

@RobWells, Sed & Awkซึ่งแท้จริงแล้วเป็นหนังสือที่ดีมากไม่มีการใช้คำใด ๆ เกี่ยวกับปริมาณโลภ / ขี้เกียจ เป็นหลักฐานที่มีเป็นอย่างที่เกิดขึ้นไม่มีคำความโลภหรือความโลภในหนังสือเล่มนี้และมีเพียงหนึ่ง แต่ไม่เกี่ยวข้องกับการเกิดขึ้นของคำว่าขี้เกียจ
Enrico Maria De Angelis

@EnricoMariaDeAngelis มันเป็น แต่ตัวอย่างไม่ได้อ้างถึงคำอย่างชัดเจน มันเกี่ยวกับวิธีการปรับแต่ง regex ของคุณให้ใช้โอเปอเรเตอร์ "not" เพื่อให้ได้การแข่งขันที่ไม่โลภ คำโลภและสันหลังยาวมาพร้อมกับเอ็นเอฟเอเอ็นเอฟเอของ Perl เมื่อพวกเขาแนะนำตัวดำเนินการเพื่อปรับเปลี่ยนพฤติกรรมการจับคู่โลภโดยเฉพาะ
Rob Wells
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.