Eu tenho um comando de substituição sed que gostaria que fosse compatível com BSD sed
e também com GNU sed
. Expressões regulares estendidas não são um problema, pois não preciso delas neste caso. Meu principal problema é a diferença na maneira como os dois sed
interpretam as sequências de escape de caracteres nosubstituiçãocordas. Minha string de substituição contém tabulações e novas linhas e eu gostaria que elas estivessem visíveis nas strings de comando para facilitar a manutenção, no entanto, o BSD sed
não interpreta as sequências de escape e o GNUsed
faz. Qual é a maneira apropriada de instruir sed
a interpretação dessas sequências de escape no BSD? Os dois trechos a seguir resumem meu problema:
GNUsed
echo ABC | sed 's/B/\n\tB\n'
rende
A
B
C
BSDsed
echo ABC | sed 's/B\n\tB\n'
rendimentos
AntBnC
Claramente, \n
e \t
não são interpretados como sequências de escape pelo BSDsed
Agora, à minha pergunta. De acordo com a sed
página de manual do BSD:
Para especificar um caractere de nova linha na string de substituição, coloque uma barra invertida antes dele.
Isso implica que eu precisaria preceder umliteralnova linha por uma barra invertida? Qual é a maneira apropriada de instruir sed
a interpretação das sequências de escape como \n
no texto de substituição?
Responder1
Você pode usar aspas do bash $'...'
para interpretar os escapes antes de passar a string para sed
.
Na página de manual do 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.
Responder2
Se você precisar escrever scripts portáteis, você deve se limitar aos recursos doPadrão POSIX(também conhecido como Single Unix, também conhecido como Especificação Base de Grupo Aberto).Edição 7 também conhecida como POSIX-1.2008é o mais recente, mas muitos sistemas ainda não terminaram de adotá-lo.Edição 6 também conhecida como POSIX-1.2001é em geral fornecido por todos os unidades modernas.
Emsed, o significado das sequências de escape como \t
e \n
não é portável, exceto que em umexpressão regular, \n
significa uma nova linha. No texto de substituição de um s
comando, \n
não é portátil, mas você pode usar a sequência barra invertida-nova linha para representar uma nova linha.
Uma maneira portátil de gerar um caractere de tabulação (ou qualquer outro caractere expresso em octal) é comtr
. Armazene o caractere em uma variável shell e substitua essa variável no trecho sed.
tab=$(echo | tr '\n' '\t')
escape=$(echo | tr '\n' '\033')
embolden () {
sed -e 's/^/'"$escape"'[1m/' -e 's/$/'"$escape"'[0m/'
}
Observe novamente que as novas linhas precisam ser expressas de forma diferente em regexes e em s
textos de substituição.
Você pode querer usarestranhoem vez de. Ele permite escapes de barra invertida, incluindo escapes octais \ooo
, em cada literal de string.
Responder3
Isso foi respondido no Stack Overflow:
https://stackoverflow.com/questions/1421478/how-do-i-use-a-new-line-replacement-in-a-bsd-sed
É exatamente o que jw013 disse.
Para inserir um tipo de guia literal ctrl+ VTab.