Изменить строку, которая существует между 2 линиями - PullRequest
0 голосов
/ 12 апреля 2020

Я хочу изменить строку, которая существует между 2 строками в абзаце. Например, у меня есть этот файл, который содержит

fruits
apple
banana
end fruits
----
all list
egg
milk
banana
end list

Я хочу изменить банан внутри блока фруктов (между фруктами и конечными фруктами) на ягоды. Как это сделать?

Ответы [ 3 ]

5 голосов
/ 12 апреля 2020

С sed:

sed '/^fruits$/,/^end fruits$/{ s/banana/berry/ }' file

Выход:

fruits
apple
berry
end fruits
----
all list
egg
milk
banana
end list
3 голосов
/ 12 апреля 2020

Не могли бы вы попробовать следующее.

awk '
/^fruits$/{
  found=1
}
found && /banana/{
  $0="your new line here"
  found=""
}
1
'  Input_file

Объяснение: Добавление подробного объяснения для приведенного выше кода.

awk '                         ##Starting awk program from here.
/^fruits$/{                   ##Checking if a line has value fruits in it then do following.
  found=1                     ##Setting value of found to 1 here, kind of FLAG to check either fruits string found in lines till now or not.
}
found && /banana/{            ##Checking condition if string banana found in line and variable found is SET then do following.
  $0="your new line here"     ##Setting current line value to new line value here.
  found=""                    ##Nullifying variable found here.
}
1                             ##Mentioning 1 will print edited/non-edited lines here.
'  Input_file                 ##Mentioning Input_file name here.
3 голосов
/ 12 апреля 2020

Это может удовлетворить ваши потребности:

awk '
fruits && /banana/ { $0 = "berry" }
/fruits/  { fruits = 1 }
/end fruits/ { fruits = 0 }
1
' 

Приведенный выше код имеет БОЛЬШОЕ допущение: все в порядке, если между «фруктами» и «конечными фруктами» появляется «банан». Если вы просто хотите заменить «бананы», вы можете изменить действие следующим образом:

awk '
fruits && /banana/ { gsub( "banana", "berry" ) }
/fruits/  { fruits = 1 }
/end fruits/ { fruits = 0 }
1
'

Выше мы заменяем все «бананы» на «ягодные», в отличие от замены всей строки ($ 0 ). И теперь, так как мы используем gsub (), мы можем фактически удалить «&& / banana /», чтобы получить это:

awk '
fruits  { gsub( "banana", "berry" ) }   # if in fruits, do sub
/fruits/  { fruits = 1 }                # weve entered the fruits block
/end fruits/ { fruits = 0 }             # weve left the block
1                                       # print each line
'

luciole предлагает использовать диапазоны. Вот еще раз программа с использованием диапазонов (и устранением флага фруктов):

awk '
/fruits/,/end fruits/  { gsub( "banana", "berry" ) }
1
'

Используя диапазон выше, программа выглядит ОЧЕНЬ похожим на ответ Сайруса.

...