sed na inserção do OSX em uma determinada linha

23

Então, eu tenho usado o 'sed' no linux por um tempo, mas tenho tido um pouco de dificuldade em usá-lo no OSX, já que 'POSIX sed' e 'GNU sed' tem tantas pequenas diferenças. Atualmente estou lutando com a forma de inserir uma linha de texto após um determinado número de linha. (neste caso, linha 4)

No linux eu faria algo assim:

sed --in-place "4 a\  mode '0755'" file.txt

Então no OSX eu tentei isso:

sed -i "" "4 a\ mode '0755'" file.txt

No entanto, isso continua me dando um erro 'caracteres extras após \ no final de um comando'. Alguma idéia do que está errado aqui? Eu tenho um erro de digitação? Ou não estou entendendo outra diferença entre versões do sed?

    
por CRThaze 17.10.2012 / 23:09

4 respostas

22

A rigor, a especificação POSIX para sed requer uma nova linha após a\ :

[1addr]a\
text

Write text to standard output as described previously.

Isso torna a escrita one-liner um pouco dolorosa, o que provavelmente é o motivo dos seguintes Extensão GNU para os comandos a , i e c :

As a GNU extension, if between the a and the newline there is other than a whitespace-\ sequence, then the text of this line, starting at the first non-whitespace character after the a, is taken as the first line of the text block. (This enables a simplification in scripting a one-line add.) This extension also works with the i and c commands.

Assim, para ser portável com a sua sintaxe sed , você precisará incluir uma nova linha após o a\ de alguma forma. A maneira mais fácil é simplesmente inserir uma nova linha entre aspas:

$ sed -e 'a\
> text'

(onde $ e > são prompts do shell). Se você achar que é um problema, bash [1] tem a $' ' sintaxe de cotação para inserir C- estilo escapa, então é só usar

sed -e 'a\'$'\n''text'

[1] e mksh (r39b +) e alguns shells não bash bourne (por exemplo, / bin / sh no FreeBSD 9 +)

    
por 18.10.2012 / 00:41
13

Conforme descrito em esta resposta , é útil ao usar comandos sed como i e a para use várias cláusulas -e "..." . Cada uma dessas cláusulas será entendida como separada por novas linhas. Os comandos i e a são difíceis de usar em scripts inline sed caso contrário (eles são projetados para uso em um arquivo de script de multiline sed invocado usando sed -f file ... ). Parece que você não pode usar a nova linha implícita introduzida pelo final de uma cláusula -e para separar o a\ e a linha de texto a ser anexada. Mas você pode usá-lo para terminar a linha de texto que será anexada.

Neste caso específico, o que você está tentando fazer pode, de fato, ser realizado com uma única cláusula -e ... . Você só precisa usar o comando a corretamente. Pelo padrão POSIX, a precisa ser seguido por um \ , então, isso precisa ser seguido por uma nova linha, depois o restante da próxima linha será inserido (até uma nova linha ou o fim do -e cláusula é encontrada). Então você poderia fazer:

sed -i "" -e $'4 a\\n'"mode '0755'" file.txt
    
por 17.10.2012 / 23:14
5

O Perl não sofre de tais idiossincrasias GNU versus não-GNU e "proprietárias". Você poderia fazer:

perl -ni.old -e 'print;if ($.==4) {print "mode 0755\n"}' file

O -n' option creates a loop that reads every line of the input file. Unlike its cousin -p (not used here) it doesn't automatically print every line read. The -i invokes in-place replacement. The argument to -i (viz. ".old") can be dropped or changed. It leaves a backup of the unmodified file. The -e sinaliza o início do script.

O $. indica o número da linha, começando com a linha-1. Assim, a linha de comando lê 'arquivo' e quando o número da linha é igual a 4, ele imprime a linha seguida por qualquer coisa que você queira injetar.

Eu gostaria de acrescentar que o Perl deve suas raízes a sed , AWK e C, então a sintaxe para substituições simples, etc. não é uma curva de aprendizado muito íngreme.

    
por 17.10.2012 / 23:38
4

O GNU sed parece ser muito mais usado que o POSIX sed, baseado em exemplos / tutoriais que usei de qualquer maneira.

Eu descobri que é muito mais fácil instalar o GNU sed em qualquer máquina OSX que eu use. Se você estiver interessado, a melhor maneira de fazer isso é instalá-lo por meio do Homebrew .

Você pode apenas $ brew install gnu-sed ou obter todos os utilitários comuns do GNU com $ brew install coreutils .

Então, quando você se deparar com um problema de sintaxe com date ou algum outro programa, você pode simplesmente usar a versão GNU. Eventualmente eu decidi que era mais fácil usar sempre as versões GNU e colocá-las antes das versões do sistema no meu PATH .

    
por 18.10.2012 / 02:38

Tags