/ / Как мога да разделя думите, съдържащи тире, използвайки sed? - regex, sed

Как мога да разделя думите, съдържащи тире, използвайки sed? - regex, sed

Бих искал да разделя думите, които използват тире sed, Линиите, които не са вътре в думите, трябва да останат такива. Например за изречението:

"the multi-modal solution is an award-winning approach in the 21st-century - however"

Бих искал изхода:

"the multi @-@ modal solution is an award @-@ winning approach in the 21st @-@ century - however"

Опитах да използвам:

sed "s/([a-zA-Z0-9]+)-([a-zA-Z0-9]+)/1 @-@ 2/g" test.txt > test2.txt

Без успех. Използвам версията OSX на sed.

Отговори:

2 за отговор № 1

Можете да използвате тази реализация без regex, като използвате awk:

s="the multi-modal solution is an award-winning approach in the 21st-century"
awk -F "-" -v OFS=" @-@ " "{$1=$1} 1" <<< "$s"

the multi @-@ modal solution is an award @-@ winning approach in the 21st @-@ century

справка: Ефективно програмиране на AWK

Sed решение (работи в OSX):

sed -E "s/([^-[:blank:]]+)-([^-[:blank:]]+)/1 @-@ 2/g" <<< "$s"

2 за отговор № 2

За да допълни sed -E разтвор в отговорът на анубхава с фиксирана версия на вашия собствен опит за решение:

sed "s/([a-zA-Z0-9]{1,})-([a-zA-Z0-9]{1,})/1 @-@ 2/g" test.txt > test2.txt

Това е ERE (ERE)продължен регулярен) количествено конструкт + трябва да се емулира {1,} в BRE (основен регулярен), който sed използва по подразбиране.


Незадължителна основна информация

Като Sundeep изтъква в коментар по въпроса, GNU sed позволява използването на + (когато не се използва -r / -E, която позволява поддръжка за EREs), но това е нестандартно разширение, което не се поддържа от macOS sed версия.

Най- sed POSIX спец само подпори Bres, специално, POSIX BREs.

Ето защо, да пиша портативен sed команди:

  • Не използвайте нито едно от двете -r (GNU sed по-нови версии на BSD sed) нито -E (както GNU, така и BSD / macOS sed)

  • Използвай само POSIX BRE характеристики, като се избягват конкретни разширения, особено:

    • употреба {1,} вместо + (еквивалент на ERE +).
    • употреба {0,1} вместо ? (еквивалент на ERE ?).
    • Избягвайте GNU | за редуване: за съжаление, POSIX BREs не подкрепят промяната.

За да се възползвате от по-мощните, модерни-синтаксични EREs, докато поддържате платформи с двете GNU и BSD sed (включително macOS):


За да научите за дадено sed специфични (нестандартни) функции на реализацията на изпълнението:

  • GNU Sed (Linux):

    • info sed, както е от GNU Sed 4.2.2, обяснява

      • GNU BRE синтаксис в глава "3.3 Преглед на синтаксиса на регулярните изрази"

        • BRE разширения са +, ?, и |; че a** се третира същото като a* (без да се налага да избягвате втория *) е вярно само за Eres.
      • GNU ERE синтаксис в "Приложение A Разширени регулярни изрази".

        • Обсъжда се обаче само контрастът с BREs и многото разширения на ERE - сред тях клавишните символи, като например d и s, твърдения за граница на думи като < / > и bОсвен това, последователностите за бягство на контролните знаци n, като tи изходни последователности, базирани на код x27 - са не там.
    • (Обратно, man re_format / man 7 regex съдържат само информация за POSIX.)

  • BSD / macOS Сед:

    • man re_format се прилага (обсъжда BREs и EREs), с изключение на раздела за подобрено функции, които не се поддържат.
    • Единствените споменати разширения са твърдения за граница на думи [[:<:]] и [[:>:]]

За подробен преглед на всичко разлики между GNU Sed и BSD Sed, виж този отговор от моите.


1 за отговор № 3

Това може да работи за вас (GNU sed):

sed "s/>-</ @-@ /g" file

Заменете хипените, заобиколени от край / начало на граници на думи с необходимия низ.


0 за отговор № 4
  s="the multi-modal solution is an award-winning approach in the 21st-century - however"
awk -F century "{gsub(/-/," @&@ ",$1)}1"  <<< "$s" OFS=century

the multi @-@ modal solution is an award @-@ winning approach in the 21st @-@ century - however