Digitando /usr/bin/env sed -f
trabalhos terminais.
Mas se usá-lo como um shebang,
#!/usr/bin/env sed -f
s/a/b/
O script falhará ao executar:
/usr/bin/env: sed -f: No such file or directory
Eu meio que acredito que isso esteja relacionado ao -f. Mas como resolver isso?
scripting
sed
executable
env
Cheng
fonte
fonte
Respostas:
Você não pode, de maneira portável, colocar mais de um argumento em uma
#!
linha . Isso significa apenas um caminho completo e um argumento (por exemplo,#!/bin/sed -f
ou#!/usr/bin/sed -f
) ou#!/usr/bin/env
nenhum argumento para o intérprete.Uma solução alternativa para obter um script portátil é usar
#!/bin/sh
um invólucro de shell, passando o script sed como um argumento da linha de comando. Observe que isso não é sancionado pelo POSIX (scripts de várias instruções devem ser escritos com um-e
argumento separado para cada instrução de portabilidade), mas funciona com muitas implementações.Para um script longo, pode ser mais conveniente usar um heredoc. Uma vantagem de um heredoc é que você não precisa citar as aspas simples, se houver. Uma desvantagem importante é que o script é alimentado para sed em sua entrada padrão, com duas conseqüências irritantes. Algumas versões do sed requerem, em
-f /dev/stdin
vez de-f -
, o que é um problema de portabilidade. Pior, o script não pode atuar como um filtro, porque a entrada padrão é o script e não pode ser os dados.A desvantagem do heredoc pode ser remediada com um uso útil de
cat
. Como isso coloca o script inteiro na linha de comando novamente, ele não é compatível com POSIX, mas é amplamente portátil na prática.Outra solução alternativa é escrever um script que possa ser analisado por sh e por sed. Isso é portátil, razoavelmente eficiente, apenas um pouco feio.
Explicações:
b
; o conteúdo não importa, desde que a função esteja sintaticamente bem formada (em particular, você não pode ter uma função vazia). Então, se verdadeiro (ou seja, sempre), executesed
o script.()
rótulo, em seguida, alguma entrada bem formada. Em seguida, umi
comando, que não tem efeito, porque é sempre ignorado. Finalmente, o()
rótulo seguido pela parte útil do script.fonte
#!/usr/bin/env
e nenhum argumento." não é redigido muito bem. Talvez "ou#!/usr/bin/env sed
nenhum argumento para sed".Existem várias implementações incompatíveis do shebang (#!), Dependendo do sistema operacional. Alguns estão criando uma lista completa de argumentos, outros estão preservando o caminho do comando e colocando todos os argumentos restantes como um único, outros estão ignorando todos os argumentos e passam apenas o caminho do comando e, finalmente, alguns estão passando a string inteira como um único comando. Você parece estar no último caso.
fonte
env está tentando encontrar um arquivo com o nome "sed -f". Você pode tentar "#! / Usr / bin / sed -f" como sua linha shebang.
fonte
No GNU coreutils v8.30 , você pode:
Este recurso foi adicionado em uma recente (2018/04/20) comprometer a
env.c
no pacote do GNU coreutils, que acrescentaram a-S
ou--split-string
opção.Na
env
página do manual:Mais exemplos estão disponíveis no manual GNU coreutils .
Se você também usar a
-v
opção para saída detalhada, poderá ver exatamente comoenv
divide a sequência de argumentos:Em
my_sed_script.sed
:Execução:
Nota: Isso se aplica apenas aos shebangs que usam
/usr/bin/env
, como--split-string
é um recurso do GNUenv
especificamente.fonte
Esta resposta fornece um caminho para uma solução elegante: /programming//a/1655389/642372
read
um heredoc em uma variável de shell.sed
.Amostra:
fonte
Gosto da solução de Walker, mas ela pode ser melhorada (colocando isso em uma resposta separada, porque os comentários não aceitam texto pré-formatado). Isso pode não funcionar em todas as versões do Linux ou Bash, mas no Ubuntu 17.10 você pode reduzir o seguinte:
Você pode remover
eval
e simplificar oread
comando, mas precisa se livrar do comentário dentro do heredoc.Além disso, para tudo o que você sempre quis saber sobre o sed, mas teve medo de perguntar, há um tutorial muito útil em http://www.grymoire.com/unix/sed.html . Isso sugere uma solução ainda melhor, à custa de perder
/usr/bin/env
e codificar o caminho para sed:Isso tem a vantagem adicional de suportar mais de uma
s///
substituição.fonte