Como posso instruir o BSD sed a interpretar seqüências de escape como \ n e \ t?

14

Eu tenho um comando de substituição sed que gostaria de ser compatível com o BSD sed , bem como com o GNU sed . Expressões regulares estendidas não são um problema, pois eu não preciso delas neste caso. Meu principal problema é a diferença na forma como os dois sed s interpretam sequências de escape de caracteres nas sequências substituição . Minha string de substituição contém abas e novas linhas e eu gostaria que elas fossem visíveis nas strings de comando para facilitar a manutenção, no entanto, o BSD sed não interpreta as seqüências de escape e o GNU sed faz . Qual é a maneira apropriada de instruir sed para interpretar essas seqüências de escape no BSD? Os dois trechos a seguir resumem meu problema:

GNU sed

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

yeilds

A
    B
C

BSD sed

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

rendimentos

AntBnC

Claramente, \n e \t não são interpretados como sequências de escape por BSD sed

Agora, para minha pergunta. De acordo com o BSD sed manpage:

To specify a newline character in the replacement string, precede it with a backslash.

Isso implica que eu precisasse preceder uma nova linha literal por uma barra invertida? Qual é a maneira apropriada de instruir sed a interpretar seqüências de escape como \n no texto de substituição?

    
por ephsmith 04.07.2012 / 19:07

3 respostas

6

Se você precisar escrever scripts portáteis, você deve se ater aos recursos no padrão POSIX (também conhecido como Single Unix aka Open Especificação da base do grupo). O problema 7 a.k.a. POSIX-1.2008 é o mais recente, mas muitos sistemas ainda não o adotaram ainda. A edição 6 a.k.a POSIX-1.2001 é em geral fornecida por todos os modernos sindicatos.

Em sed , o significado de sequências de escape como \t e \n é não é portável, exceto que em um regex , \n significa uma nova linha. No texto de substituição de um comando s , \n não é portátil, mas você pode usar a sequência de barras invertidas-newline para representar uma nova linha.

Uma forma portátil de gerar um caractere de tabulação (ou qualquer outro caractere expresso em octal) é com tr . Armazene o caractere em uma variável do shell e substitua essa variável no snippet de sed.

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

Observe novamente que as novas linhas precisam ser expressas de maneira diferente nas expressões regulares e nos textos de substituição s .

Você pode usar o awk . Ele permite escapes de barra invertida, incluindo octal escapes \ooo , em todo literal de string.

    
por 05.07.2012 / 02:35
7

Você pode usar o bash $'...' quoting para interpretar os escapes antes de passar a string para sed .

Na página do 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.
    
por 04.07.2012 / 23:59
3

Isso foi respondido no Stack Overflow:

link

É praticamente exatamente o que jw013 disse.

Para inserir um tipo de tabulação literal ctrl + V Tab .

    
por 04.07.2012 / 19:46

Tags