Три різні sed
команди:
sed '$!N;s/"[^"]*"\n<[^>]*>/other characters /;P;D'
sed -e :n -e '$!N;s/"[^"]*"\n<[^>]*>/other characters /;tn'
sed -e :n -e '$!N;/"$/{$!bn' -e '};s/"[^"]*"\n<[^>]*>/other characters /g'
Усі вони s///
базуються на базовій команді ubstitution:
s/"[^"]*"\n<[^>]*>/other characters /
Вони також намагаються подбати про обробку останнього рядка, оскільки вони sed
мають тенденцію відрізнятися від результатів у крайових випадках. Це значення $!
якого є адресою, що відповідає кожному рядку, який !
не є $
останнім.
Всі вони також використовують команду N
ext, щоб додати наступний рядок вводу до простору візерунка, наступного за \n
символом ewline. Кожен, хто sed
певний час працював, навчиться покладатися на \n
персонаж ewline - адже єдиний спосіб отримати його - це явно помістити його туди.
Усі три намагаються прочитати якомога менше вводу, перш ніж вживати заходів - sed
діє якнайшвидше, але не потрібно читати у вхідному файлі, перш ніж робити це.
Хоча вони і всі N
, всі три відрізняються за методами рекурсії.
Перша команда
Перша команда використовує дуже простий N;P;D
цикл. Ці три команди вбудовані в будь-який POSIX-сумісний sed
і вони добре доповнюють одна одну.
N
- як уже згадувалося, додає N
рядок введення ext до простору візерунка після вставленого \n
роздільника ewline.
P
- подобається p
; він P
вказує на простір шаблону, але лише до першого \n
персонажу, що виникає на лінії виходу. І так, враховуючи наступний ввід / команду:
printf %s\\n one two | sed '$!N;P;d'
sed
P
rints тільки один . Однак, з ...
D
- подобається d
; він D
виділяє простір шаблону і починає черговий цикл ліній. На відміну від цього d
, D
видаляє лише до першої \n
зустрічної ewline у просторі шаблонів. Якщо в \n
символі ewline є більше простору шаблону, sed
починається наступний цикл рядка з того, що залишається. Якщо d
в попередньому прикладі були замінені D
, наприклад, sed
буде P
Рінту як один і два .
Ця команда повторюється лише для рядків, які не відповідають s///
заяві ubstitution. Оскільки s///
ubstitution видаляє \n
доданий ewline N
, ніколи нічого не залишається, коли sed
D
вибирається простір шаблону.
Тести можна зробити для застосування P
та / або D
вибірково, але є й інші команди, які краще відповідають цій стратегії. Оскільки рекурсія реалізована для обробки послідовних рядків , які відповідають тільки частини правила заміни, послідовні послідовності ліній , відповідних обидва кінці на s///
ubstitution не працюють добре.:
Враховуючи цей вхід:
first "line"
<second>"line"
<second>"line"
<second>line and so on
... він друкує ...
first other characters "line"
<second>other characters line and so on
Однак це справляється
first "line"
second "line"
<second>line
...просто добре.
Друге командування
Ця команда дуже схожа на третю. Обидва використовують етикетку :b
ranch / t
est (що також продемонстровано у відповіді Йозефа Р. тут ) і повторно повертаються до неї за певних умов.
-e :n -e
- портативні sed
скрипти обмежують :
визначення мітки або \n
ewline, або новим вбудованим -e
оператором xecution.
:n
- визначає мітку з назвою n
. Це можна повернути в будь-який час за допомогою bn
або tn
.
tn
- команда t
est повертається до вказаної мітки (або, якщо такої немає, виходить із сценарію для поточного циклу рядків), якщо будь-яке s///
вставлення, оскільки або мітка була визначена, або з моменту останнього виклику ests t
успішного.
У цій команді відбувається рекурсія відповідних рядків. Якщо sed
успішно замінює візерунок на інші символи , sed
повертається до :n
мітки та повторює спробу. Якщо s///
введення не виконується, sed
авторський відбиток-пробіл шаблону і починається наступний цикл рядків.
Це, як правило, краще обробляє послідовні послідовності. Там, де останній не вдався, це друкує:
first other characters other characters other characters line and so on
Третє командування
Як було сказано, логіка тут дуже схожа на останню, але тест є більш явним.
/"$/bn
- це sed
тест. Оскільки команда b
ranch є функцією цієї адреси, вона sed
повернеться лише b
до :n
того, як \n
додається ewline, і простір шаблону все ще закінчується "
подвійною цитатою.
Між ними N
і b
наскільки це можливо, зроблено якнайменше - таким чином sed
можна дуже швидко зібрати рівно стільки, скільки потрібно, щоб переконатися, що наступний рядок не може відповідати вашому правилу. Тут s///
ув'язнення відрізняється тим, що в ньому використовується g
лобальний прапор - і тому він буде робити всі необхідні заміни одразу. За умови однакового введення ця команда виводить однаково останньому.
\n
заяву ewline ви робите чому я питаю. люди рідко запитують, чи можуть вони зробити так,s//\n/
як ви можете з GNUsed
, хоча більшість інших людейsed
відхилять цю втечу з правого боку. все-таки\n
втеча буде працювати зліва в будь-якому POSIX,sed
і ви можете переносити їх так, як,y/c/\n/
хоча це матиме такий же ефект, якs/c/\n/g
і так завжди, як корисний.