Как мне указать BSD sed интерпретировать escape-последовательности, такие как \n и \t?

Как мне указать BSD sed интерпретировать escape-последовательности, такие как \n и \t?

У меня есть команда замены sed, которую я хотел бы сделать совместимой как с BSD, sedтак и с GNU sed. Расширенные регулярные выражения не являются проблемой, поскольку в данном случае они мне не нужны. Моя главная проблема заключается в разнице в том, как эти два seds интерпретируют escape-последовательности символов взаменастроки. Моя строка замены содержит табуляции и символы новой строки, и я хотел бы, чтобы они были видны в командных строках для простоты обслуживания, однако BSD sedне интерпретирует escape-последовательности и GNUsed делает. Каков подходящий способ указания sedинтерпретировать эти escape-последовательности на BSD? Следующие два фрагмента олицетворяют мою проблему:

ГНУsed

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

урожайность

A
    B
C

БСДsed

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

урожайность

AntBnC

Очевидно, \nи \tне интерпретируются BSD как escape-последовательности.sed

Теперь, к моему вопросу. Согласно странице руководства BSD sed:

Чтобы указать символ новой строки в строке замены, поставьте перед ним обратную косую черту.

Означает ли это, что мне нужно будет предшествоватьбуквальныйновая строка с помощью обратной косой черты? Каков подходящий способ указать, sedкак интерпретировать escape-последовательности, как \nв тексте замены?

решение1

Вы можете использовать кавычки bash $'...'для интерпретации экранированных символов перед передачей строки в sed.

Из страницы руководства bash:

   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.

решение2

Если вам нужно писать переносимые скрипты, вам следует придерживаться функций встандарт POSIX(также известная как Single Unix, также известная как Open Group Base Specification).Выпуск 7, он же POSIX-1.2008является новейшей версией, но многие системы еще не полностью ее внедрили.Выпуск 6, он же 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, в каждом строковом литерале.

решение3

На этот вопрос уже ответили на Stack Overflow:

https://stackoverflow.com/questions/1421478/how-do-i-use-a-new-line-replacement-in-a-bsd-sed

Это практически то же самое, что сказал jw013.

Чтобы вставить буквальную табуляцию, введите ctrl+ VTab.

Связанный контент