ลบข้อมูลระหว่างสองบรรทัดรวม

วิธีใดคือวิธีที่ดีที่สุดในการค้นหาและลบข้อมูลระหว่างข้อความสองบรรทัด รวมถึงบรรทัดแรกแต่ไม่ใช่บรรทัดที่สอง

สตริง 1: SECTION - PAY 500 - ที่จะถูกลบ

ข้อมูลที่จะลบ บรรทัดข้อความแบบสุ่ม

สตริง 2: SECTION - Pay 400 - อยู่ต่อ

นี่คือเอกสาร word ที่มีความยาวประมาณ 3,000 หน้า แต่ฉันมีเวอร์ชันข้อความให้ใช้งานได้ด้วย ฉันจะเริ่มเขียนสคริปต์ทุบตีสำหรับงานดังกล่าวได้ที่ไหน

ตัวอย่างเนื้อหาไฟล์:

text 
SECTION - PAY 500    (to be deleted)
text                 (to be deleted)
SECTION - Pay 400
text 
SECTION - PAY 500    (to be deleted)
text                 (to be deleted)
SECTION - Pay 400
text 

หลังจากลบไปแล้วก็จะได้ผลลัพธ์แบบนี้

text 
SECTION - Pay 400
text
SECTION - Pay 400
text

person eveo    schedule 28.12.2012    source แหล่งที่มา
comment
สมมติว่าคุณต้องการลบบล็อกจำนวนมากออกจากเอกสาร 3000 หน้าของคุณ คุณช่วยยกตัวอย่างเพิ่มเติมให้เราฟังหน่อยได้ไหม คุณคาดว่าจะลบบล็อกได้กี่บล็อก? จะมีความคลุมเครือระหว่างข้อความในเครื่องหมายส่วนหรือไม่ เช่น SECTION - PAY 5000 ขอให้โชคดี.   -  person shellter    schedule 29.12.2012
comment
sed ฉันจะไปที่นี่ไหม   -  person squiguy    schedule 29.12.2012


คำตอบ (4)


โซลูชันที่มีมาตรฐาน sed:

sed "/$START/,/$END/ { /$END/"'!'" d; }"

ซึ่งหมายความว่าสำหรับช่วงเริ่มต้นที่ /$START/ และสิ้นสุดที่ /$END/ การกระทำ { /$END/! d; } จะเสร็จสิ้น ซึ่งจะ d (ลบ) สำหรับทุกบรรทัดที่ไม่ใช่ /$END/

"'!'" นั้นแปลก แต่วิธีเดียวที่จะหลีกเลี่ยงสัญลักษณ์ ! จากการขยาย bash

person Dmytro Sirenko    schedule 28.12.2012

ฉันคิดว่าคุณสามารถแยกไฟล์ทีละบรรทัดได้ค่อนข้างเร็ว สิ่งที่คุณกำลังจะเก็บถาวรดูเหมือนจะไม่ซับซ้อนเกินกว่าจะเข้าใจได้

copy=true
while read line; do
    if [ $copy ]; then
        if [[ "$line" == "SECTION - PAY 500"* ]]; then copy=; continue; fi
        echo "$line" >> outputfile
    else
        if [[ "$line" == "SECTION - Pay 400"* ]]; then copy=true; fi
    fi
done < inputfile

และการทำเช่นนี้ทำให้เรามีบางอย่างที่เหมือนกับเครื่องจักรทัวริงตัวเล็กๆ อยู่ด้วย!

person J. Katzwinkel    schedule 29.12.2012

sed โซลูชันมาตรฐานอื่น (แปลกน้อยกว่า ;)): sed "/$END/ p; /$START/,/$END/ d;"

หมายเหตุด้านข้าง: sed บางเวอร์ชันยังรองรับการแก้ไขไฟล์แบบแทนที่ด้วย หากจำเป็น

และสคริปต์ทุบตีเต็มเปี่ยม:

#! /bin/bash

if [ "x$1" = "x-r" ]
then
    regex=1
    shift
else
    regex=0
fi

if [ $# -lt 2 ]
then
    echo "Usage: del.sh [-r] start end"
    exit 1
fi

start="$1"
end="$2"

function matches
{
    [[ ( regex -eq 1 && "$1" =~ $2 ) || ( regex -eq 0 && "$1" == "$2" ) ]]
}

del=0
while read line
do
    # end marker, must be printed
    if matches "$line" "$end"
    then
        del=0
    fi
    # start marker, must be deleted
    if matches "$line" "$start"
    then
        del=1
    fi
    if [ $del -eq 0 ]
    then
        echo "$line"
    fi
done
person Jester    schedule 29.12.2012

วิธีแก้ไขง่ายๆ : ลองวิธีนี้

Inputfile.txt

text 
SECTION - PAY 500    
text                 
SECTION - Pay 400
text 
SECTION - PAY 500   
text                 
SECTION - Pay 400
text

รหัส

awk '/500/{print;getline;next}1' Inputfile.txt | sed '/500/d'

เอาต์พุต

text 
SECTION - Pay 400
text 
SECTION - Pay 400
text 
person Debaditya    schedule 29.12.2012