Sie können tragbarerweise nicht mehr als ein Argument in eine #!
Zeile setzen . Das bedeutet nur einen vollständigen Pfad und ein Argument (z. B. #!/bin/sed -f
oder #!/usr/bin/sed -f
) oder #!/usr/bin/env
kein Argument für den Interpreter.
Eine Problemumgehung, um ein portables Skript zu erhalten, ist die Verwendung #!/bin/sh
eines Shell-Wrappers, der das sed-Skript als Befehlszeilenargument übergibt. Beachten Sie, dass dies von POSIX nicht genehmigt wird (Multianweisungsskripte müssen aus Gründen der -e
Portabilität für jede Anweisung mit einem separaten Argument geschrieben werden ), aber es funktioniert mit vielen Implementierungen.
#!/bin/sh
exec sed '
s/a/b/
' "$@"
Für ein langes Skript ist es möglicherweise praktischer, einen Heredoc zu verwenden. Ein Vorteil eines Heredocs ist, dass Sie die einzelnen Anführungszeichen nicht in Anführungszeichen setzen müssen, sofern vorhanden. Ein großer Nachteil ist, dass das Skript auf der Standardeingabe basiert, was zwei ärgerliche Folgen hat. Einige Versionen von sed erfordern -f /dev/stdin
stattdessen -f -
, was ein Problem für die Portabilität darstellt. Schlimmer noch, das Skript kann nicht als Filter fungieren, da die Standardeingabe das Skript ist und nicht die Daten sein können.
#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF
Der Nachteil des Heredocs kann durch eine sinnvolle Verwendung von behoben werden cat
. Da dadurch das gesamte Skript wieder in der Befehlszeile angezeigt wird, ist es nicht POSIX-kompatibel, aber in der Praxis weitgehend portierbar.
#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF
Eine andere Problemumgehung besteht darin, ein Skript zu schreiben, das sowohl von sh als auch von sed analysiert werden kann. Dies ist tragbar, einigermaßen effizient, nur ein wenig hässlich.
#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/
Erklärungen:
- Unter sh: definiere eine aufgerufene Funktion
b
; Der Inhalt spielt keine Rolle, solange die Funktion syntaktisch korrekt aufgebaut ist (insbesondere können Sie keine leere Funktion haben). Wenn dies der Fall ist (dh immer), führen Sie sed
das Skript aus.
- Unter sed: zum
()
Label verzweigen , dann wohlgeformte Eingabe. Dann ein i
Befehl, der keine Wirkung hat, weil er immer übersprungen wird. Schließlich das ()
Etikett, gefolgt vom nützlichen Teil des Skripts.
- Getestet unter GNU sed, BusyBox und OpenBSD. (Sie können mit etwas Einfacherem in GNU sed davonkommen, aber OpenBSD sed ist wählerisch in Bezug auf die Teile, die es überspringt.)