errore sed: "riferimento non valido \ 1 sull'RHS del comando" s "


104

Eseguo diversi comandi di sostituzione come nucleo di uno script colorize per Maven . Uno dei sedcomandi utilizza un'espressione regolare che funziona nella shell come discusso qui . L'attuale implementazione (non funzionante) può essere trovata qui .

Quando includo una delle varianti del comando nello script si verifica un comportamento diverso:

Variante 1:

$ sed -re "s/([a-zA-Z0-9./\\ :-]+)/\1/g"

Adattato alla sceneggiatura:

-re "s/WARNING: ([a-zA-Z0-9./\\ :-]+)/${warn}WARNING: \1${c_end}/g" \

Errore: la shell restituisce le stesse informazioni come se dovessi digitare $ sed. Strano!?


Variante 2:

$ sed -e "s/\([a-zA-Z0-9./\\ :-]\+\)/\1/g"

Adattato alla sceneggiatura:

-e "s/WARNING: \([a-zA-Z0-9./\\ :-]\+\)/${warn}WARNING: \1${c_end}/g" \

Errore:

sed: -e espressione # 7, char 59: riferimento non valido \ 1 sull'RHS del comando `s '


10
Nel mio caso avevo combinato una -i(opzione di modifica in posizione) con -re, risultante in -ire(quindi -iconsumava il reframmento come SUFFIXargomento e quindi la modalità regex estesa non era abilitata); cambiandolo per -i -rerisolvere il problema.
Janaka Bandara

È anche da notare che le virgolette singole 'e le virgolette doppie "vengono trattate in modo leggermente diverso, soprattutto durante l'interpretazione $vars. Ad esempio: sudo sh -c "sed -r -i 's/(^.+_supplicant.conf)/\1${MTXT}/' /etc/network/interfaces"funziona, ma: sudo sh -c 'sed -r -i "s/(^.+_supplicant.conf)/\1${MTXT}/" /etc/network/interfaces'non funziona.
not2qubit

Risposte:


52

Non è necessario acquisire effettivamente perché funzioni? cioè per la variante 2:

-r -e "s/WARNING: (\([a-zA-Z0-9./\\ :-]\+\))/${warn}WARNING: \1${c_end}/g" \

(Nota: non testato)

Senza l'argomento -r i riferimenti all'indietro (come \ 1) non funzioneranno.


42
L' -ropzione per sed sembra essere necessaria affinché il riferimento a ritroso funzioni. Ad esempio sed -e 's/([[:digit:]])/is a digit/'funziona ma sed -e 's/([[:digit:]])/\1 is a digit/produce l'errore originale senza -rsedersi. NOTA: la prima invocazione di sed cerca un letterale (<digit>)e non è un gruppo di cattura.
Andrew Falanga

Il commento sotto la risposta è in realtà una risposta. Forse puoi modificare la tua risposta per rispecchiarla.
miroxlav

@AndrewFalanga avresti dovuto pubblicare il tuo commento come risposta
sanmai

2
Non importa che il mio errore sia stato quello di usare -ireinvece di usare -ri. L'ordine conta :-)
m3nda

54

Questo errore è comune per le parentesi senza caratteri di escape. Sfuggili e riprova.


Per esempio:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n(.)/\1/g

Dovrebbe essere preceduto da barre rovesciate prima di ogni parentesi:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g

6
Attenzione, se usi -rnon devi sfuggire alle parentesi.
qräbnö

13

Se l' opzione -r/ --regexp-extendednon viene fornita, è necessario eseguire l'escape delle parentesi di acquisizione.


5

Hai bisogno di scappare /dopo il.

sed -e "s/\([a-zA-Z0-9.\/\\ :-]\+\)/\1/g"

O se non vuoi preoccuparti di scappare, usa |

sed -e "s|\([a-zA-Z0-9./\\ :-]\+\)|\1|g"

MODIFICARE:

sed -e "s|WARNING: \([a-zA-Z0-9.-/\\ :]+\)|${warn}WARNING: \1${c_end}|g"

Sembra ragionevole. Ma non funziona nel contesto della sceneggiatura.
JJD

Scusate. La modifica genera l'errore: sed: -e expression #7, char 58: Invalid range end. La risposta di @Denis funziona.
JJD

2
Ok, quindi +1 per la risposta di
@Denis
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.