Три різні 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мають тенденцію відрізнятися від результатів у крайових випадках. Це значення $!якого є адресою, що відповідає кожному рядку, який !не є $останнім.
Всі вони також використовують команду Next, щоб додати наступний рядок вводу до простору візерунка, наступного за \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 Prints тільки один . Однак, з ...
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
...просто добре.
Друге командування
Ця команда дуже схожа на третю. Обидва використовують етикетку :branch / test (що також продемонстровано у відповіді Йозефа Р. тут ) і повторно повертаються до неї за певних умов.
-e :n -e- портативні sedскрипти обмежують :визначення мітки або \newline, або новим вбудованим -eоператором xecution.
:n- визначає мітку з назвою n. Це можна повернути в будь-який час за допомогою bnабо tn.
tn- команда test повертається до вказаної мітки (або, якщо такої немає, виходить із сценарію для поточного циклу рядків), якщо будь-яке s///вставлення, оскільки або мітка була визначена, або з моменту останнього виклику ests tуспішного.
У цій команді відбувається рекурсія відповідних рядків. Якщо sedуспішно замінює візерунок на інші символи , sedповертається до :nмітки та повторює спробу. Якщо s///введення не виконується, sedавторський відбиток-пробіл шаблону і починається наступний цикл рядків.
Це, як правило, краще обробляє послідовні послідовності. Там, де останній не вдався, це друкує:
first other characters other characters other characters line and so on
Третє командування
Як було сказано, логіка тут дуже схожа на останню, але тест є більш явним.
/"$/bn- це sedтест. Оскільки команда branch є функцією цієї адреси, вона 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і так завжди, як корисний.