Escribiendo /usr/bin/env sed -f
en terminal funciona.
Pero si lo usas como un shebang,
#!/usr/bin/env sed -f
s/a/b/
El script no se ejecutará:
/usr/bin/env: sed -f: No such file or directory
Creo que está relacionado con -f. ¿Pero cómo resolver esto?
scripting
sed
executable
env
Cheng
fuente
fuente
Respuestas:
No puede, de forma portátil, poner más de un argumento en una
#!
línea . Eso significa solo una ruta completa y un argumento (p. Ej.#!/bin/sed -f
O#!/usr/bin/sed -f
), o#!/usr/bin/env
sin argumento para el intérprete.Una solución para obtener un script portátil es usar
#!/bin/sh
un contenedor de shell, pasando el script sed como un argumento de línea de comandos. Tenga en cuenta que POSIX no lo autoriza (los scripts de instrucciones múltiples deben escribirse con un-e
argumento separado para cada instrucción de portabilidad), pero funciona con muchas implementaciones.Para una secuencia de comandos larga, puede ser más conveniente usar un heredoc. Una ventaja de un heredoc es que no necesita citar las comillas simples dentro, si las hay. Una desventaja importante es que el script se alimenta a sed en su entrada estándar, con dos consecuencias molestas. Algunas versiones de sed requieren en
-f /dev/stdin
lugar de-f -
, lo cual es un problema para la portabilidad. Peor aún, el script no puede actuar como un filtro, porque la entrada estándar es el script y no puede ser la información.La desventaja del heredoc puede remediarse mediante un uso útil de
cat
. Dado que esto vuelve a colocar todo el script en la línea de comando, no es compatible con POSIX, sino que es prácticamente portátil en la práctica.Otra solución es escribir un script que pueda analizarse tanto por sh como por sed. Esto es portátil, razonablemente eficiente, solo un poco feo.
Explicaciones:
b
; el contenido no importa siempre que la función esté sintácticamente bien formada (en particular, no puede tener una función vacía). Entonces, si es verdadero (es decir, siempre), ejecutesed
en el script.()
etiqueta, luego una entrada bien formada. Luego, uni
comando, que no tiene ningún efecto porque siempre se omite. Finalmente la()
etiqueta seguida de la parte útil del guión.fuente
#!/usr/bin/env
y sin argumento". No está redactado muy bien. Quizás "o#!/usr/bin/env sed
no hay argumento para sed".Hay varias implementaciones incompatibles de shebang (#!) Dependiendo del sistema operativo. Algunos están construyendo una lista completa de argumentos, algunos conservan la ruta del comando y colocan todos los argumentos restantes como uno solo, algunos ignoran todos los argumentos y pasan solo la ruta del comando, y finalmente, algunos pasan la cadena completa como un solo mando. Parece que estás en el último caso.
fuente
env está tratando de encontrar un archivo con el nombre "sed -f". Puede probar "#! / Usr / bin / sed -f" como su línea shebang.
fuente
A partir de GNU coreutils v8.30 , puede hacer:
Esta característica se agregó en una reciente (04/20/2018) se comprometen a
env.c
en el paquete GNU coreutils, que añadió el-S
o--split-string
opción.Desde la
env
página del manual:Hay más ejemplos disponibles en el manual de GNU coreutils .
Si también usa la
-v
opción de salida detallada, puede ver exactamente cómoenv
divide la cadena de argumentos:En
my_sed_script.sed
:Ejecución:
Nota: Esto solo se aplica a shebangs que usan
/usr/bin/env
, ya que--split-string
es una característicaenv
específica de GNU .fuente
Esta respuesta proporciona un camino hacia una solución elegante: /programming//a/1655389/642372
read
un heredoc en una variable de shell.sed
.Muestra:
fuente
Me gusta la solución de Walker, pero se puede mejorar (poniendo esto en una respuesta separada porque los comentarios no aceptan texto preformateado). Es posible que esto no funcione en todas las versiones de Linux o Bash, pero en Ubuntu 17.10 puede reducir esto a lo siguiente:
Puede eliminar
eval
y simplificar elread
comando, pero debe deshacerse del comentario dentro del heredoc.Además, para todo lo que siempre quiso saber sobre sed pero tenía miedo de preguntar, hay un tutorial muy útil en http://www.grymoire.com/unix/sed.html . Esto sugiere una solución aún mejor, a expensas de perder
/usr/bin/env
y codificar el camino hacia sed:Esto tiene la ventaja adicional de admitir más de un
s///
reemplazo.fuente