Warum beeinflusst -a in "#! / Bin / sh -a" sed und "set -a" nicht?

20

Wenn ich die folgende .sh-Datei ausführe:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Das Ergebnis ist ein Fehler:

sed: -e Ausdruck # 1, char 18: Ungültiges Bereichsende

Aber wenn ich die folgende .sh-Datei laufen lasse:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Es läuft ohne Fehler. Soll der zweite Code nicht gleich dem ersten sein? Warum der Fehler im ersten?

Rodrigo
quelle
Nicht alle shsind gleich. Auch sind nicht alle sed gleich. Welches verwenden shSie? In welchem ​​Betriebssystem? und welche sed (vielleicht? sed --versionwenn es nicht scheitert)?
Isaac
1
Einstellung LC_COLLATE=C(oder POSIX) für den Aufruf zur sedBehebung des Problems
Jeff Schaller
4
Ein Unterschied, den ich gefunden habe: Das erste Skript ruft sed (und vermutlich jedes andere Dienstprogramm) POSIXLY_CORRECT=yin der Umgebung auf, das zweite nicht POSIXLY_CORRECTin der Umgebung. Die Shell, von der ich beide Skripte aufgerufen habe, befindet sich nicht POSIXLY_CORRECTin ihrer Umgebung.
Mark Plotnick
1
Ah, echo "a" | POSIXLY_CORRECT=y sed -e 's/[\d001-\d008]//g' reproduzieren Sie Ihr Problem
Isaac
1
Die Bestätigung, dass das oben Genannte für mich genau so fehlschlägt, wie es das OP auf CentOS 7.x gezeigt hat - GNU bash, Version 4.2.46 (2) -Release (x86_64-redhat-linux-gnu) und CentOS Linux Release 7.5.1804 (Core) .
slm

Antworten:

31

Wenn bash mit dem Namen aufgerufen wird sh, geschieht Folgendes :

if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
    act_like_sh++;

und setzt die POSIXLY_CORRECTShell-Variable später aufy :

if (act_like_sh)
  {
    bind_variable ("POSIXLY_CORRECT", "y", 0);
    sv_strict_posix ("POSIXLY_CORRECT");
  }

bind_variableCalls bind_variable_internal, die, wenn das Shell-Attribut azur Zeit aktiviert ist (was der Fall wäre, wenn Sie die Shell mit aufrufen -a), die Shell-Variable als exportiert markieren .

Also in deinem ersten Drehbuch:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

sedwird POSIXLY_CORRECT=yin seiner Umgebung mit aufgerufen , worüber es sich beschwert [\d001-\d008]. (Dasselbe passiert, wenn sed die --posixOption erhält .)

In GNU Sed, wird ein Escape - Code für das Zeichen , dessen Zahlenwert in der Basis-10 ist NNN , aber in der POSIX - Modus ist dies innerhalb einer Klammerausdruck Behinderte, so , bedeutet wörtlich die Zeichen , usw., wobei der Bereich ist von zu . Kommt in der Reihenfolge der Zeichencodes vor (und der Bereich umfasst alle Ziffern außer Null sowie alle Großbuchstaben und einige Sonderzeichen). In dem Gebietsschema, das Sie verwendet haben, wird jedoch zuvor sortiert , sodass der Bereich ungültig ist.\dNNN[\d001-\d008]\d1\1\en_US.UTF-8\1

In Ihrem zweiten Skript:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Obwohl POSIXLY_CORRECTes in der Shell festgelegt ist, wird es nicht exportiert, sodass sed ohne POSIXLY_CORRECTin der Umgebung aufgerufen wird und sed mit GNU-Erweiterungen ausgeführt wird.

Wenn Sie export POSIXLY_CORRECTin der Nähe des oberen Bereichs Ihres zweiten Skripts hinzufügen , werden Sie auch sed bemängeln sehen.

Mark Plotnick
quelle
6
Für mich ist das ein Fehler.
Stéphane Chazelas
1
Heilige Muschel Horror, Batman! Das ist eine interessante Marotte (und ein bisschen einer Änderung um ein Problem zu sehen , die aus kommt /bin/shtatsächlich zu sein Bash). Das gleiche passiert, wenn POSIXLY_CORRECTes sich vor dem shStart von Bash in der Umgebung befindet : Es wird auch als weitergegeben POSIXLY_CORRECT=y.
ilkkachu
3
@StevenPenny, POSIXLY_CORRECT befindet sich jedoch nicht in der Umgebung, wenn die Shell gestartet wird , und das Skript legt dies nicht fest. Die Muschel tut es. Es erstellt eine Umgebungsvariable aus dem Nichts, was besonders schlimm ist, da es dies in einem Modus tut, in dem es sein soll, und versucht, standardkonform zu sein.
Ilkkachu
4
FWIW, Bash scheint auch nicht zu dokumentieren, dass es sich von selbst einstellen würde POSIXLY_CORRECT. In der Liste der Auswirkungen des POSIX-Modus wird dies nicht erwähnt, und die Beschreibung der Variablen besagt lediglich, dass durch das Festlegen der Wirkung die Shell in den POSIX-Modus versetzt wird, nicht umgekehrt.
Ilkkachu
1
@ilkkachu. Getan. Ich denke, die POSIX-Spezifikation sollte auch aktualisiert werden, um zu klären, welche Variablen betroffen sind allexport.
Stéphane Chazelas