Удалить текст до и после строки, но с ограничителями

avatar
murilo.xd
8 апреля 2018 в 03:18
126
6
2

Я использовал sed для удаления строк с определенными словами:

string=${line##* }
sed "/$string/d" $dhcp 

Неудобство в том, что есть части текста, которые я не могу безопасно удалить.

В идеале это должно выглядеть примерно так:

пример: ввод:

 config host
        mac '00:a0:00:00:00:00'
        option name 'laptop1'
        option dns '1'

config host
        option mac '00:a0:00:00:00:00'
        option name 'string'
        option dns '1'

 config host
        option name 'laptop3'
        mac '00:a0:00:00:00:00'
        option dns '1'

Вывод

config host
        option mac '00:a0:00:00:00:00'
        option name 'laptop1'
        option dns '1'

 config host
        option name 'laptop3'
        mac '00:a0:00:00:00:00'
        option dns '1'

Какой способ лучше всего подходит для этого?

благодарна за внимание

Источник
murilo.xd
10 апреля 2018 в 03:40
0

Я выбрал, основываясь на переносимости, но даже сложно сказать, какой ответ действительно лучший. Спасибо вам всем! / awk -v RS= -v ORS='\n\n' '!/'$string'/' файл

Ed Morton
10 апреля 2018 в 08:42
1

Не позволяйте переменной оболочки (особенно не заключенной в кавычки) расширяться, чтобы стать частью тела сценария оболочки. См. cfajohnson.com/shell/cus-faq-2.html#Q24. Наиболее распространенным способом использования значения переменной оболочки внутри этого awk-скрипта будет awk -v RS= -v ORS='\n\n' -v str="$string" '$0!~str' file.

murilo.xd
13 июля 2018 в 22:09
1

Спасибо, это работало очень хорошо в переменных с большим количеством слов.

Ответы (6)

avatar
Ed Morton
8 апреля 2018 в 18:17
0

sed предназначен для выполнения s/old/new/ на отдельных строках ввода это все. Хотя в нем есть миллион загадочных комбинаций символов для выполнения других задач, все они устарели в середине 1980-х, когда был изобретен awk, и, если они не мазохисты, сегодня люди используют их только для умственных упражнений, а не для реального кода.

$ awk -v RS= -v ORS='\n\n' '!/string/' file
 config host
        mac '00:a0:00:00:00:00'
        option name 'laptop1'
        option dns '1'

 config host
        option name 'laptop3'
        mac '00:a0:00:00:00:00'
        option dns '1'

.

$ awk -v RS= -v ORS='\n\n' '!/laptop1/' file
config host
        option mac '00:a0:00:00:00:00'
        option name 'string'
        option dns '1'

 config host
        option name 'laptop3'
        mac '00:a0:00:00:00:00'
        option dns '1'
avatar
potong
9 апреля 2018 в 08:02
0

Это может сработать для вас (GNU sed):

sed '/config host/{:a;N;/^\s*$/M!ba;/string/d}' file

Собрать строки, начинающиеся с config host, в пустую строку. Если строки содержат string, удалите эти строки, иначе напечатайте их.

avatar
ctac_
8 апреля 2018 в 09:24
0

Вы можете попробовать этот gnu sed

sed '/./!d;:A;$bB;N;/\n$/!bA;:B;/string/d' infile
avatar
shaiki siegal
8 апреля 2018 в 05:17
0

**awk**

    set str1=laptop1 ; //set string for removed section 

    awk -v RS="config host" -v a=$str '($0!~a)&&(NR>1) {printf "%s", RS $0 }' file

1) RS="config host" - установить разделитель записи в желаемую строку .

2) -v str1=$str1 получить аргумент (строка для поиска в записанной строке, в нашем случае $str1=laptop1).

3) ($0!~str1)&&(NR>1) — записи, не содержащие строку $str.

4) {printf "%s",RS $0 } - вывести разделитель записи и записанную строку

Ed Morton
8 апреля 2018 в 18:28
0

Вы должны упомянуть, что он будет работать только с GNU awk из-за многосимвольного RS.

avatar
RavinderSingh13
8 апреля 2018 в 04:25
0

Следующие awk могут помочь вам в этом.

awk '/config host/{if(val){print val};non_flag=val=""} /option name \047string\047/{non_flag=1;val=""}  !non_flag && NF{val=val?val ORS $0:$0} END{if(val){print val}}'  Input_file

Теперь также добавлена ​​форма решения без одного вкладыша.

awk '
/config host/{
  if(val){
     print val};
  non_flag=val=""
}
/option name \047string\047/{
  non_flag=1;
  val=""
}
!non_flag && NF{
  val=val?val ORS $0:$0
}
END{
  if(val){
    print val}
}'   Input_file

Объяснение: Сейчас также добавлено объяснение кода выше.

awk '
/config host/{                ##Searching for text config host in a line if it is there then do following.
  if(val){                    ##If variable val is NOT NULL then do following.
     print val};              ##printing the value of variable val here.
  non_flag=val=""             ##Nullifying the variables non_flag and val here.
}
/option name \047string\047/{ ##Searching for string option name 'string' here if it is found then do following.
  non_flag=1;                 ##Setting up the value of variable non_flag as 1 here.
  val=""                      ##Nullifying the variable named val here.
}
!non_flag && NF{              ##Checking conditions if variable non_flag is NULL and line is NOT a empty line then do following.
  val=val?val ORS $0:$0       ##Create variable named val and each time cursor comes here concatenate its value with its own value.
}
END{                          ##Starting END section of awk code here.
  if(val){                    ##Checking if variable val is NOT NULL then do following,
    print val}                ##Printing variable val value here.
}' Input_file                 ##Mentioning Input_file name here.

ПРИМЕЧАНИЕ: В случае, если Input_file является переменной оболочки, которая выглядит как из вашего поста, измените Input_file на <454890261>304649>.

avatar
Andre Figueiredo
8 апреля 2018 в 03:37
0
cat $dhcp | tr '\n' '\r' | sed -e "s/\r\r.*'string'.*\r\r/\r\r/" | tr '\r' '\n'

Объяснение:

  1. tr '\n' '\r':
    Замените \n на \r, чтобы разрешить sed работать с "линиями разрыва".
  2. sed -e "s/\r\r.*'string'.*\r\r/\r\r/":
    Заменить пустой строкой вхождение 'string' и родственные ему символы, пока не будут найдены двойные разрывные строки.
  3. tr '\r' '\n':
    Изменить обратно \r на \n