Diferenças entre sed no Mac OSX e outro sed “padrão”?

58

Estou tendo alguns problemas ao usar uma resposta fornecida neste site para essa pergunta sobre um comando sed para substituir uma linha em branco por duas outras linhas de conteúdo , e foi criada se o comando sed no Mac OS (10.6.7 para eu) é diferente. Eu não acho que é, mas queria saber se os outros neste site pensavam de forma diferente.

    
por Peter Grill 24.05.2011 / 20:16

3 respostas

41

O comportamento dos utilitários de shell diferem de maneiras menores entre as variantes unix. Existem muitas variantes unix , com um complexo histórico . Existem esforços de padronização como o POSIX e seu superconjunto especificação Single UNIX . Atualmente, a maioria dos sistemas implementa o POSIX: 2001, também conhecido como Single UNIX Specification versão 3 , com pequenos desvios e muitas extensões. A especificação Unix única não é um tutorial, mas a versão 3 é legível se você já tiver uma ideia do que um comando está fazendo. Você pode consultá-lo para saber se algum recurso é padrão ou uma extensão de um sistema específico.

A maioria dos usuários unix usa o Linux e não usou nenhuma outra variante. O Linux vem com os utilitários GNU , que muitas vezes têm muitas extensões para o padrão. Então você encontrará um monte de código lá fora, que funciona no Linux, mas não em outros unices, porque depende dessas extensões.

Em relação ao sed, consulte a especificação única do sed para o mínimo que todo sistema deve ter para apoiar, a página do manual em seu sistema para o que sua implementação suporta, e o manual do GNU sed para o que a maioria das pessoas usa.

Uma das extensões fora do padrão no GNU sed é o suporte a vários comandos executados juntos. Por exemplo, este programa GNU sed imprime todas as linhas contendo a , mas altera b para c first:

sed -ne '/a/ {s/b/c/g; p}'

{ e } são, na verdade, comandos separados, portanto, para total portabilidade, é necessário especificá-los em linhas separadas (em um arquivo) ou em argumentos -e separados (na linha de comando). A falta de um separador de comando após { e o uso de ; como um separador de comando são extensões comuns. A falta de um separador de comando antes de } é uma extensão menos comum. Isto é compatível com os padrões:

sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'

Isso é fora do padrão, mas comumente aceito:

sed -ne '/a/ { s/b/c/g; p; }'

Outra extensão não padrão, porém comum, é o uso de \n para significar uma nova linha em um texto de substituição s (o uso em um regexp é padrão). O método portátil é incluir a barra invertida-newline no script sed. Outra extensão comum é \+ , \? e \| em regexps para significar um ou mais, no máximo um e alternação; As expressões regulares básicas portáteis não possuem nenhuma delas. Por exemplo, o primeiro comando é uma maneira não portátil de substituir sequências contíguas de espaços em branco por uma nova linha; o segundo comando é equivalente aos padrões.

sed -e 's/ \+/\n/'
sed -e 's/  */\
/'
    
por 24.05.2011 / 21:22
52

O OS X atualmente vem com um FreeBSD sed de 2005. A maioria das diferenças abaixo também se aplica a outras versões do BSD sed.

O sed do OS X usa -E para o ERE e o GNU sed usa -r . -E é um alias para -r no GNU sed (adicionado em 4.2, não documentado até 4.3). Versões mais recentes do FreeBSD e NetBSD sed suportam -E e -r . O OpenBSD sed suporta apenas -E .

-i '' funciona com o sed do OS X, mas não com o GNU sed. -i funciona com o GNU sed, versões recentes do NetBSD, OpenBSD sed , mas não o sed do OS X. -i -e funciona com ambos, mas no caso do FreeBSD sed faz um backup do arquivo original com -e anexado ao nome do arquivo (e você não precisa passar mais de uma expressão para sed ).

O GNU sed interpreta sequências de escape como \t , \n , \x011 , \w , \b e \n . O sed do OS X e o POSIX sed interpretam apenas s (mas não na parte de substituição de \| ).

O GNU sed interpreta \+ , \? e \( no BRE, mas o OS X é sed e o POSIX sed não. \) , \{ , \} e ; são POSIX BRE.

O GNU sed permite omitir } ou uma nova linha antes de i , mas o sed do OS X não.

a (insert), c (append) e i (change) devem ser seguidos por uma barra invertida e uma nova linha no sed do OS X e no POSIX sed, mas não no GNU sed. O GNU sed adiciona uma nova linha ausente após o texto inserido por a , c ou sed 1ia , mas o sed do OS X não. Por exemplo, sed $'1i\\na\n' é uma alternativa do GNU para printf a|sed -n p .

Por exemplo, I adiciona uma nova linha no sed do OS X, mas não no GNU sed.

O sed do OS X não suporta os modificadores M (insensitivo a maiúsculas) ou I (multi-linha). Versões mais recentes do suporte do FreeBSD sed -s .

O sed do OS X não suporta --separate ( -u ), --unbuffered ( -z ) ou --null-data ( -a ).

Uma opção do BSD que não é suportada pelo GNU sed é w , o que torna %code% anexado a um arquivo em vez de truncar um arquivo.

Exemplos de comandos do GNU sed que não funcionam com o sed do OS X:

sed /pattern/,+2d # like 'sed '/pattern/{N;N;d;}''
sed -n 0~3p # like 'awk NR%3==0'
sed /pattern/Q # like 'awk '/pattern/{exit}1'' or 'sed -n '/pattern/,$!p''
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a shell command
sed -n l0 # 0 disables wrapping
    
por 25.05.2014 / 20:33
4

A melhor maneira que encontrei de ter o mesmo trabalho de script no Linux e no Mac é:

sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
  rm -- "${TARGET}.bak"
    
por 23.07.2017 / 06:52