Удалить данные между двумя строками включительно

Каков наилучший способ поиска и удаления данных между двумя строками текста, включая первую строку, но не вторую.

Строка 1: SECTION - PAY 500 - удалить

данные для удаления, случайные строки текста

Строка 2: SECTION - Pay 400 - остаться

Это текстовый документ объемом около 3000 страниц, но у меня также есть текстовая версия для работы. С чего бы мне начать писать сценарий bash для такой задачи?

пример содержимого файла:

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 также поддерживают редактирование файлов на месте, если это необходимо.

И полноценный bash-скрипт:

#! /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

Простое решение: попробуйте этот способ

Входной файл.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