Na presente edição
Stéphane Chazelas POSIXifies (novamente) o meu sed
formatação através da inserção de uma -e
pausa xpression e outra -e
declaração xpression. Agora, posso perguntar a ele por que, nos comentários, suponho, mas já é a revisão número 18 dessa resposta e quase todas as anteriores já eram graças a brindes semelhantes (se você puder ver comentários excluídos, saberá o que Quero dizer) . Além disso, acho que estou perto o suficiente para entender por que expressar isso de uma maneira que possa ser mais útil em geral. Então aqui está esperando ...
Geralmente, prefiro manter minhas sed
-e
impressões totais em um, se eu puder, mas também tenho uma preferência maior por estar em conformidade com as especificações o mais próximo possível, especialmente quando a diferença chega a não mais que um <space>
e um -e
. Mas não posso fazer isso se não entendo por que deveria. Aqui está um breve resumo do estado atual do meu entendimento:
a
' -e '
interrupção pode substituir portabilidade uma quebra de linha desed
script\n
em umased
instrução de linha de comando ... Eu sou confuso sobre o porquêa chave de fechamento em uma
sed
{
função}
deve ser precedida por uma\n
quebra de linha de linha, conforme indicado aqui:- O
<right-brace>
deve ser precedido por a<newline>
e pode ser precedido ou seguido por<blank>
caracteres.
- O
uma
\n
pausa ewline é igualmente necessário seguir qualquer uso de ...a
,b
,c
,i
,r
,t
,w
, ou:
.
Mas não entendo claramente como a definição de {
função }
se relaciona com o !
operador not. A única menção que encontro do operador de negação nos estados de especificação:
- Uma função pode ser precedida por um ou mais
!
caracteres; nesse caso, a função será aplicada se os endereços não selecionarem o espaço do padrão.
Isso significa que o uso de um !
implica {
aparelho }
? O que dizer dos $!
comandos - eles também devem ser separados por ' -e '
intervalos? Foi isso que foi abordado quando Stéphane mais recentemente POSIXificou minha resposta?
Eu acho que é o !
operador de negação ou a b
declaração do rancho que ele aborda em sua edição - ou possivelmente é ao mesmo tempo -, mas eu não sei e gostaria de fazê-lo. Se for apenas a b
declaração do rancho, acredito que um d
funcionaria em seu lugar e eliminaria a necessidade do ' -e '
intervalo, mas prefiro ter certeza antes de arriscar uma resposta três vezes POSIXificada . Você pode ajudar?
Afinal , arrisquei , mas não com muita certeza ...
b;n;:b
, você está ramificando para o rótulo chamado";n;:b"
seds históricos e POSIX (e o GNU sed não é nesse sentido).:
papel - você dirigiu isso para casa meses atrás. Mas não entendo completamente por que o segundosed
comando foi similarmente POSIXificado .sed
é muito incerta para mim. Solicitei esclarecimentos algumas vezes no passado, mas acho que não foi atualizado como resultado. Um bom teste é tentar usar o baú da ferramenta de herança (Solaris one, derivado do original e no qual a especificação POSIX se baseia amplamente).s///
as ubstitutions devem aceitar encadeamento com a ; . fica embaçado com os comandos que devem ser delimitados com uma nova linha e como-e
pode ficar nesse caso - pelo menos para mim. Ainda estou tropeçando em algosed
que não os interpreta de maneira bastante intercambiável.;
antes de uma nova linha - uma nova linha é boa. Honestamente, você poderia ficar sem o-e
e tudo inteiramente e apenas escrever um arquivo como#!/bin/sed
com cada comando em uma nova linha - ou aqueles que não requerem esses delimitadores, em vez disso, delimitados por;
. Os que fazer exigem novas linhas são geralmente os que levam entrada arbitrária -:
nomes de rótulos e comandos que se referem a eles comob
out
ou fechar}
curlies para funções our
ead ew
rito que levam argumentos de nome de arquivo. Todos eles portàvelmente precisam ser seguidos por\n
.Respostas:
Portanto, já é hora de essa pergunta ter uma resposta e, embora eu tenha intuitivamente descoberto como fazer isso corretamente em praticamente todos os casos, há algum tempo atrás, só recentemente consegui concretizar esse entendimento com o texto do padrão. . Na verdade, é declarado lá de maneira bastante simples - eu simplesmente ignorei isso muitas vezes, eu acho.
As partes relevantes do texto são encontradas sob o título ...
Comandos de edição em
sed
:O texto do argumento deve consistir em uma ou mais linhas. Cada linha
\n
eletrônica incorporada no texto deve ser precedida por uma\
barra invertida. Outras barras invertidas no texto serão removidas e o caractere a seguir será tratado literalmente.Os verbos
r
ew
comando e ow
sinalizador para os
comando assumem um parâmetro opcional rfile (ou wfile ), separado da letra ou sinalizador do verbo do comando por um ou mais<blank>s
; implementações podem permitir separação zero como uma extensão.Comando verbos que não
{
,a
,b
,c
,i
,r
,t
,w
,:
, e#
pode ser seguido por um;
ponto e vírgula, opcional<blank>s
, e outro verbo de comando. No entanto, quando os
verbo de comando é usado com ow
sinalizador, segui-lo com outro comando dessa maneira produz resultados indefinidos....dentro...
Opções: Múltiplas
-e
e-f
opções podem ser especificadas. Todos os comandos devem ser adicionados ao script na ordem especificada, independentemente de sua origem.-e
script - Adicione os comandos de edição especificados pelo argumento da opção de script ao final do script dos comandos de edição. O argumento de opção de script deve ter as mesmas propriedades que o operando do script , descrito na seção OPERANDS .-f
script_file - adicione os comandos de edição no arquivo script_file ao final do script.E por último em ...
Operandos:
\n
ewline.Portanto, quando você o toma em conjunto, faz sentido que qualquer comando que seja opcionalmente seguido por um parâmetro arbitrário sem um delimitador predefinido (em oposição a,
s d sub d repl d flag
por exemplo) deva delimitar em uma linha de linha sem escape\n
.É possível argumentar que se
;
trata de um delimitador predefinido, mas, nesse caso, o uso de;
para qualquer um dos[aic]
comandos exigiria que um analisador separado fosse incluído na implementação especificamente para esses três comandos - separados, ou seja, do analisador usado para[:brw]
, por exemplo. Ou então a implementação teria que exigir que;
também houvesse uma barra invertida escapada dentro do parâmetro de texto e ela só se tornaria mais complicada a partir daí.Se eu estivesse escrevendo um
sed
que desejasse ser compatível e eficiente, espero não escrever um analisador separado, exceto que talvez[aic]
gere um erro de sintaxe se não for imediatamente seguido por um\n
ewline. Mas esse é um problema simples de tokenização - o caso do delimitador final é geralmente o mais problemático. Eu escreveria assim:...e...
... se comportaria de maneira muito semelhante, pois o primeiro criaria e gravaria em um arquivo chamado:
... e o segundo acrescentaria um bloco de texto à linha atual na saída, como ...
... porque ambos compartilhariam o mesmo código de análise para o parâmetro
E em relação ao
{ ... }
e$!
edição - bem, eu estava longe lá. Um único comando precedido por um endereço não é uma função, mas apenas um comando endereçado. Quase todos os comandos - incluindo a{
definição de função}
são especificados para aceitar/one/
ou/one/,/two/
endereçar - com exceção da definição de#
comentário e:
rótulo . E um endereço pode ser um número de linha ou um expresso regular e pode ser negado!
. Então todos ...... pode ser seguido por um
;
e mais comandos de acordo com o padrão, mas se mais comandos forem necessários para um único endereço, e esse endereço não deve ser reavaliado após a execução de cada comando, uma{
função}
deve ser usada como:... onde
{
não pode ser seguido na mesma linha por um fechamento}
e que um fechamento}
não pode ocorrer, exceto no início de uma linha. Porém, se um comando contido não\n
puder ser seguido por uma linha de e-mail, ele também não precisará estar dentro da função. Portanto, todas ass///
substituições acima - e até a}
chave de fechamento , podem ser seguidas de maneira portável por;
ponto e vírgula e outros comandos.Eu continuo falando sobre
\n
delimitadores de linha eletrônica, mas a pergunta é sobre-e
declarações xpression, eu sei. Mas os dois são realmente o mesmo, e a principal relação é que um script pode ser um argumento literal da linha de comando ou um arquivo com um dos dois-[ef]
, e que ambos são interpretados como arquivos de texto (que são especificados para terminar em um\n
linha), mas nenhuma delas precisa terminar em uma\n
linha. Com isso, posso razoavelmente (espero) inferir que um\0NUL
argumento delimitado implica uma linha final de\n
ew e, como todos os argumentos de invocação têm pelo menos) um\0NUL
delimitador de qualquer maneira, então eles devem funcionar bem.De fato, na prática, em todos os casos, exceto aquele em que o padrão especifica que uma
\
nova linha com escape de barra invertida deve ser necessária, eu encontrei portably ...... para trabalhar tão bem. E em todos os casos - novamente, na prática - onde um
\n
ewline não escapado deve ser necessário ...... funcionou para mim também. A única exceção que mencionei acima é ...
... que não funciona para nenhuma implementação em nenhum dos meus testes. Tenho certeza de que isso remete ao requisito do arquivo de texto e ao fato de que
s///
vem com um delimitador e, portanto, não há razão para que uma única instrução deva abranger\0NUL
argumentos delimitados.Portanto, concluindo, aqui está um breve resumo de maneiras portáteis de escrever vários tipos de
sed
comandos:Para qualquer um de
[aic]
:...ou...
Para qualquer um dos
[:rwtb]
lugares em que o parâmetro é opcional (para todos, exceto:
), mas a linha de\n
chamada delimitadora não é . Observe que eu nunca tive um motivo para tentar vários parâmetros de rótulo de linha , como seria usado com[:tb]
, mas essew
registro /r
leitura de várias linhas nos parâmetros do arquivo [rw] geralmente é aceito sem perguntas porsed
s que testei desde que o\n
ewline incorporado é escapado com uma\
barra invertida. Ainda assim, o padrão não especifica diretamente que os parâmetros label e [rw] devem ser analisados de forma idêntica ao textoparâmetros e não faz menção de\n
linhas eletrônicas em relação aos dois primeiros, exceto quando os delimita....ou...
... onde o
<space>
acima é opcional para[:tb]
.E por ultimo...
...ou...
... onde qualquer um dos comandos mencionados acima (exceto
:
) também aceita pelo menos um endereço e que pode ser um número/
regular/
ou de linha e pode ser negado!
, mas se mais de um comando for necessário para uma única avaliação do endereço , chaves de delimitação de{
contexto de função}
devem ser usadas. Uma função pode conter até vários\n
comandos delimitados por linha de linha, mas cada um deve ser delimitado dentro dos chavetas, como seria caso contrário.E é assim que se escreve
sed
scripts portáteis .fonte