Як я можу доручити BSD sed інтерпретувати послідовності втечі, такі як \ n і \ t?


14

У мене є команда заміни sed, що я хотів би бути сумісним як з BSD, sedтак і з GNU sed. Розширені регулярні вирази не є проблемою, тому що мені в цьому випадку вони не потрібні. Моя основна проблема полягає в різниці в тому, що два sedінтерпретують послідовності виходу символів у рядках заміни . Мій рядок заміни містить вкладки та нові рядки, і я хотів би, щоб вони були видимими в командних рядках для зручності обслуговування, однак, BSD sedне інтерпретує послідовності виходу, а GNU sed робить . Який відповідний спосіб доручити sedінтерпретувати ці послідовності евакуації на BSD? Наступні два фрагменти уособлюють мою проблему:

GNU sed

echo ABC | sed 's/B/\n\tB\n'

yeilds

A
    B
C

BSD sed

echo ABC | sed 's/B\n\tB\n'

врожайність

AntBnC

Зрозуміло, \nі\t BSD не інтерпретується як послідовність втечіsed

Тепер до мого питання. Відповідно до сторінки BSD sed:

Щоб вказати символ рядка в рядку заміни, передуйте його з косою рисою.

Чи означає це, що мені потрібно передувати буквальний новий рядок зворотним нахилом? Який спосіб підказати sedінтерпретувати послідовності втечі, як \nу тексті заміни?


2
BSD sed - це не GNU sed, і я не думаю, що він підтримує такі втечі у виході. Вам доведеться або вставити буквальні символи, встановити GNU sed, або переключитися на щось, що підтримує такі втечі, як awk.
jw013

@ jw013, я чітко розумію різницю між ними. Встановлення GNU sed не є можливим. Я сподівався знайти достатньо спільної точки зору між ними, щоб досягти того, що я маю після sed. Зрештою, мабуть, буде сенс використовувати awk. Отже, що ви думаєте про інтерпретацію цитованої мною сторінки BSD sed?
ephsmith

2
Так, вам потрібно буде використовувати буквальні вкладки та нові рядки, а для нових рядків вам також потрібно передувати їх зворотній косою рисою, яка в основному є механізмом продовження рядків.
jw013

@ jw013, дякую за ваші чудові відповіді. У цей момент, задля технічного обслуговування, я прийму ваші поради та переробляю своє рішення на відміну.
ephsmith

Хороший вибір - awk - це набагато кращий план, ніж зараз прийнята відповідь :)
jw013

Відповіді:


6

Якщо вам потрібно написати портативні сценарії, вам слід дотримуватися функцій стандарту POSIX (він же, Single Unix aka Open Group Base Specification). Випуск 7 aka POSIX-1.2008 - це останнє, але багато систем ще не прийняли його. Випуск 6 aka POSIX-1.2001 загалом надається усіма сучасними об'єднаннями.

У СЕД , сенс керуючих послідовностей , як \tі \nне є портативним, за винятком того, що в регулярних виразах , \nпозначає символ нового рядка. Текст заміни для sкоманди \nне є портативним, але ви можете використовувати послідовно-зворотну косу рису-новий рядок для позначення нового рядка.

Портативний спосіб генерування символу табуляції (або будь-якого іншого символу, вираженого у вісімці), є за допомогою tr. Збережіть символ у змінній оболонки та замініть цю змінну у фрагменті sed.

tab=$(echo | tr '\n' '\t')
escape=$(echo | tr '\n' '\033')
embolden () {
  sed -e 's/^/'"$escape"'[1m/' -e 's/$/'"$escape"'[0m/'
}

Зауважте ще раз, що нові рядки потрібно виражати по-різному в регулярних виразах і в s текстах заміни.

Ви можете замість цього використати awk . Це дозволяє виконувати зворотні нахили, включаючи восьмеричні втечі \ooo, у кожному прямому рядку.


7

Можна використовувати баш $'...' цитування для інтерпретації вхідних даних, перш ніж передавати рядок до sed.

З сторінки "bash man":

   Words  of  the  form  $'string'  are  treated specially.  The word
   expands to string, with backslash-escaped characters  replaced  as
   specified  by the ANSI C standard.  Backslash escape sequences, if
   present, are decoded as follows:
          \a     alert (bell)
          \b     backspace
          \e     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \nnn   the eight-bit character whose  value  is  the  octal
                 value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadeci-
                 mal value HH (one or two hex digits)
          \cx    a control-x character

   The expanded result is single-quoted, as if the  dollar  sign  had
   not been present.

   A  double-quoted  string  preceded by a dollar sign ($) will cause
   the string to be translated according to the current  locale.   If
   the  current locale is C or POSIX, the dollar sign is ignored.  If
   the string is translated and replaced, the replacement is  double-
   quoted.

3

На це відповідь на "Переповнення стека":

/programming/1421478/how-do-i-use-a-new-line-replacement-in-a-bsd-sed

Це майже саме те, що сказав jw013.

Для того, щоб вставити буквальну вкладку, введіть ctrl+ VTab.


дякую за довідку. Я ненавиджу, що пошуки в Google не повернули це посилання: D
ephsmith

1
Пропозиція вкладки ctrl-V залежить від оболонки, наприклад, вона не працюватиме в рибі.
anddam

Ніколи не вживаючи рибу, я не знав, але добре знати.
Багамат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.