La façon d'utiliser `/ usr / bin / env sed -f` en shebang?

Taper /usr/bin/env sed -f dans le terminal fonctionne.

Mais si vous l'utilisez comme un shebang,

 #!/usr/bin/env sed -fs/a/b/ 

Le script échouera à s'exécuter:

 /usr/bin/env: sed -f: No such file or directory 

Je crois que c'est lié au -f. Mais comment résoudre cela?

    Vous ne pouvez pas, portablement, mettre plus d'un argument sur un #! ligne . Cela signifie seulement un path complet et un argument (par exemple #!/bin/sed -f ou #!/usr/bin/sed -f ) ou #!/usr/bin/env et aucun argument pour l'interpréteur.

    Une solution de contournement pour get un script portable est d'utiliser #!/bin/sh et un wrapper shell, en passant le script sed comme argument de command line. Notez que ceci n'est pas sanctionné par POSIX (les scripts multi-instructions doivent être écrits avec un argument -e distinct pour chaque instruction de portabilité), mais cela fonctionne avec de nombreuses implémentations.

     #!/bin/sh exec sed ' s/a/b/ ' "$@" 

    Pour un long script, il peut être plus pratique d'utiliser un heredoc. Un avantage d'un heredoc est que vous n'avez pas besoin de citer les guillemets simples à l'intérieur, le cas échéant. Un inconvénient majeur est que le script est alimenté à Sed sur son input standard, avec deux conséquences ennuyeuses. Certaines versions de sed nécessitent -f /dev/stdin au lieu de -f - , ce qui pose un problème pour la portabilité. Pire, le script ne peut pas agir comme un filter, car l'input standard est le script et ne peut pas être datatables.

     #!/bin/sh exec sed -f - -- "$@" <<'EOF' s/a/b/ EOF 

    L'inconvénient de l'heredoc peut être corrigé par une utilisation utile de cat . Comme cela met à nouveau le script sur la command line, ce n'est pas conforme à POSIX, mais il est largement portable dans la pratique.

     #!/bin/sh exec sed "$(cat <<'EOF')" -- "$@" s/a/b/ EOF 

    Une autre solution consiste à écrire un script qui peut être analysé à la fois par sh et par sed. C'est portable, raisonnablement efficace, juste un peu moche.

     #! /bin/sh b () { x } i\ f true; then exec sed -f "$0" "$@"; fi : () # sed script starts here s/a/b/ 

    Explications:

    • Sous sh: définir une fonction appelée b ; le contenu n'a pas d'importance tant que la fonction est syntaxiquement bien formée (en particulier, vous ne pouvez pas avoir une fonction vide). Ensuite, si true (c'est-à-dire toujours), exécutez sed sur le script.
    • Sous sed: twigz sur l'label () , puis une input bien formée. Ensuite, une command i , qui n'a aucun effet car elle est toujours ignorée. Enfin, l'label () suivie de la partie utile du script.
    • Testé sous GNU sed, BusyBox et OpenBSD. (Vous pouvez vous en sortir avec quelque chose de plus simple sur GNU sed, mais OpenBSD sed est pointilleux sur les parties qu'il saute.)

    Il existe diverses implémentations incompatibles du shebang (#!) En fonction du operating system. Certains construisent une list d'arguments complète, d'autres conservent le path de la command et mettent tous les arguments restants en un seul, certains ignorent tous les arguments et ne passent que le path de la command, et enfin, certains passent la string entière comme un seul order. Vous semblez être dans ce dernier cas.

    Env essaie de find un file avec le nom "sed -f". Vous pouvez essayer "#! / Usr / bin / sed -f" comme ligne de votre shebang.