2013-05-19 18 views
50

Eseguo diversi comandi di sostituzione come nucleo di uno colorize script for maven. Uno dei comandi sed utilizza un'espressione regolare che funziona nella shell come discussed here. L'attuale implementazione (non funzionante) può essere trovata here.sed: "riferimento non valido 1 su 's' RHS del comando"

Quando includo una delle varianti del comando sul comportamento diverso script di verifica:

Variante 1:

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

Adattato allo script:

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

Errore: Il lei ll restituisce le stesse informazioni come se scrivessi $ sed. Strano!?


Variante 2:

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

Adattato allo script:

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

Errore:

sed: -e expression #7, char 59: invalid reference \1 on `s' command's RHS

+5

Nel mio caso avevo combinato una '-i' (opzione Modifica posto in) con '-re', risultante in' -ire' (quindi '-i' stava consumando il frammento' re' come argomento 'SUFFIX' e quindi la modalità regex estesa non veniva abilitata); cambiandolo in '-i -re' è stato risolto il problema. –

+0

Si noti anche che le virgolette singole "" e le virgolette "" sono trattate in modo leggermente diverso, specialmente nell'interpretazione di '$ 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'' no. – not2qubit

risposta

15

Non hai bisogno di catturare effettivamente affinché funzioni? vale a dire per la variante 2:

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

(Nota: non testata)

+22

L'opzione' -r' di sed sembra essere necessaria perché il riferimento a ritroso funzioni, ad esempio 'sed -e 's/([[ : digit:]])/è una cifra/'' funziona ma 'sed -e 's/([[: digit:]])/\ 1 è una cifra /' produce l'errore originale senza '-r' per sed . ** NOTA: ** la prima chiamata di ricerca sed per un letterale '()' e ** non è ** un gruppo di cattura. –

+0

Il commento sotto la risposta è in realtà una risposta. Forse puoi modificare la tua risposta a Riflettilo – miroxlav

+0

@AndrewFalanga avresti dovuto pubblicare il tuo commento come risposta – sanmai

4

devi sfuggire alla / dopo la .

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

Oppure, se non si vuole preoccupare di fuggire, utilizzare |

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

MODIFICA:

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

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

+0

Controlla la mia modifica, forse può aiutare – slackmart

+0

Siamo spiacenti. La modifica genera l'errore: 'sed: -e espressione # 7, char 58: fine intervallo non valido'. La risposta di @Denis funziona. – JJD

36

Questo errore è comune per le parentesi che non sono sfuggite. Fuggeteli e riprovate.


Ad esempio:

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

dovrebbero essere preceduti da backslash prima di ogni parentesi:

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

Attenzione, se si utilizza '-r' non è necessario sfuggire alle parentesi. –

Problemi correlati