Perché -a in "#! / Bin / sh -a" influenza sed e "set -a" no?


20

Se eseguo il seguente file .sh:

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

Il risultato è un errore:

sed: -e espressione # 1, carattere 18: fine intervallo non valido

Ma se eseguo il seguente file .sh:

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

Funziona senza errori. Il secondo codice non dovrebbe essere equivalente al primo? Perché l'errore nel primo?


Non tutti shsono uguali. Né tutti i sed sono equivalenti. Che shstai usando? In quale sistema operativo? e quale sed (forse? sed --versionse non fallisce)?
Isacco,

1
impostazione LC_COLLATE=C(o POSIX) affinché la chiamata sedrisolva il problema
Jeff Schaller

4
Una differenza ho riscontrato: il primo script richiama sed (e presumibilmente qualsiasi altra utilità) POSIXLY_CORRECT=ynell'ambiente, il secondo non ha POSIXLY_CORRECTnell'ambiente. La shell da cui invoco entrambi gli script non ha POSIXLY_CORRECTnel suo ambiente.
Mark Plotnick,

1
Ah, echo "a" | POSIXLY_CORRECT=y sed -e 's/[\d001-\d008]//g' riproduci il tuo problema
Isaac,

1
Confermando che quanto sopra fallisce per me esattamente come OP ha mostrato su CentOS 7.x - GNU bash, versione 4.2.46 (2) -release (x86_64-redhat-linux-gnu) e CentOS Linux versione 7.5.1804 (Core) .
slm

Risposte:


31

Quando bash viene chiamato con il nome sh, lo fa :

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

e successivamente imposta la POSIXLY_CORRECTvariabile shell suy :

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

bind_variablechiamate bind_variable_internal, che, se l'attributo shell aè attivo al momento (come sarebbe se invocassi la shell -a), contrassegna la variabile shell come esportata .

Quindi nel tuo primo script:

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

sedviene invocato POSIXLY_CORRECT=ynel suo ambiente, il che lo farà lamentare [\d001-\d008]. (La stessa cosa accade se a sed viene data l' --posixopzione.)

In GNU sed, è un codice di escape per il carattere il cui valore numerico in base 10 è NNN , ma in modalità POSIX, questo è disabilitato all'interno un'espressione staffa, quindi , significa letteralmente i caratteri , ecc, con l'intervallo essendo da a . In ordine di codici di caratteri, viene prima (e l'intervallo include tutte le cifre tranne zero, più tutte le lettere maiuscole e alcuni caratteri speciali). Nelle impostazioni internazionali che stavi utilizzando, ordina prima , tuttavia, l'intervallo non è valido.\dNNN[\d001-\d008]\d1\1\en_US.UTF-8\1

Nel tuo secondo script:

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

anche se POSIXLY_CORRECTè impostato nella shell, non viene esportato, quindi sed viene invocato senza POSIXLY_CORRECTnell'ambiente e sed funziona con estensioni GNU.

Se aggiungi export POSIXLY_CORRECTvicino all'inizio del secondo script, vedrai anche lamentarsi.


6
Per me è un bug.
Stéphane Chazelas,

1
horror conchiglia sacra, Batman! Questo è un capriccio interessante (e un po 'di un cambiamento di vedere un problema che deriva dal /bin/shfatto di essere Bash). Lo stesso accade se si POSIXLY_CORRECTtrova nell'ambiente prima dell'inizio di shBash: lo passerà anche come POSIXLY_CORRECT=y.
ilkkachu,

3
@StevenPenny, ma POSIXLY_CORRECT non è nell'ambiente all'avvio della shell e lo script non lo imposta. La shell lo fa. Crea una variabile d'ambiente dal nulla, il che è molto più grave dal momento che lo fa in una modalità in cui dovrebbe essere, e cerca di essere conforme agli standard.
ilkkachu,

4
FWIW, anche Bash non sembra documentare che si sarebbe impostato POSIXLY_CORRECTda solo. Non è menzionato nell'elenco degli effetti della modalità POSIX e la descrizione della variabile dice solo che impostandola si cambia la shell in modalità POSIX, non viceversa.
ilkkachu,

1
@ilkkachu. Fatto. Penso che anche le specifiche POSIX debbano essere aggiornate per chiarire quali variabili sono interessate allexport.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.