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

Я использовал 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'

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

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

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

murilo.xd 10.04.2018 05:40

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

Ed Morton 10.04.2018 10:42

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

murilo.xd 14.07.2018 00:09
В чем разница между методом "==" и equals()
В чем разница между методом "==" и equals()
Это один из наиболее часто задаваемых вопросов новичкам на собеседовании. Давайте обсудим его на примере.
Замена символа по определенному индексу в JavaScript
Замена символа по определенному индексу в JavaScript
В JavaScript существует несколько способов заменить символ в строке по определенному индексу.
2
3
113
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Следующий 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 на "$dhcp".

** 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 } - распечатать разделитель записей и записанную строку

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

Ed Morton 08.04.2018 20:28

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

sed '/./!d;:A;$bB;N;/\n$/!bA;:B;/string/d' infile
Ответ принят как подходящий

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'

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

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

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

Другие вопросы по теме