2012-10-15 3 views
5

voglio conservare una parte specifica di un risultato abbinato come variabile da utilizzare per la sostituzione in seguito. Mi piacerebbe tenerlo in un solo liner invece di trovare la variabile che ho bisogno prima.Usare segnaposti/variabili in un comando sed

durante la configurazione di apache, e l'uso mod_rewrite, è venire indicata parti specifiche dei modelli da utilizzare come variabili, in questo modo:

RewriteRule ^www.example.com/page/(.*)$ http://www.example.com/page.php?page=$1 [R=301,L] 

la parte del pattern match che è contenuta all'interno delle parentesi viene memorizzato $ 1 per uso successivo. Quindi, se l'URL è stato www.example.com/page/home, si sarebbe sostituito con www.example.com/page.php?page=home. Quindi la parte "casa" della partita è stata salvata in $ 1 perché era la parte del pattern all'interno della parentesi.

voglio qualcosa di simile a questa funzionalità con un comando sed, ho bisogno di sostituire automaticamente molte stringhe in un file di dump SQL, aggiungere tavolo goccia se esiste comandi prima di ogni tavolo creare, ma ho bisogno di sapere il nome della tabella di fare questo, quindi se il file di dump contiene qualcosa come:

... 
CREATE TABLE `orders` 
... 

ho bisogno di eseguire qualcosa di simile:

cat dump.sql | sed "s/CREATE TABLE `(.*)`/DROP TABLE IF EXISTS $1\N CREATE TABLE `$1`/g" 

per ottenere il risultato di:

... 
DROP TABLE IF EXISTS `orders` 
CREATE TABLE `orders` 
... 

Sto usando la sintassi mod_rewrite nel comando sed come un esempio logico di ciò che sto cercando di fare.

Qualche suggerimento?

risposta

8
sed '/CREATE TABLE \([^ ]*\)/ s//DROP TABLE IF EXISTS \1; &/' 

Trova un'istruzione CREATE TABLE e acquisisci il nome della tabella. Sostituirlo con 'DROP TABLE IF EXISTS' e il nome della tabella, oltre a un punto e virgola per terminare la dichiarazione, e una copia di ciò che è stato abbinato a preservare l'istruzione CREATE TABLE.

Questo è un classico sed notazione. Dato che stai utilizzando bash, è possibile che tu stia utilizzando GNU sed e che sia necessario aggiungere --posix per utilizzare tale notazione, oppure dovrai impostare lo script per utilizzare le espressioni regex non standard di sed di GNU. Non ho anche tentato di inserire una nuova riga nell'output. Puoi farlo con GNU sed se è abbastanza importante per te.

I punti chiave sono le parentesi (che in genere devono essere preceduti da escape con una barra rovesciata) sono il meccanismo di cattura e il numero di backslash è il meccanismo di sostituzione.

+0

Grazie per questa spiegazione, si è completamente risposto alla mia domanda. –

6
sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \1\n &/g" dump.sql 

prova:

kent$ cat t.txt 

CREATE TABLE `orders` 
... 

CREATE TABLE `foo` 
... 
... 

CREATE TABLE `bar` 
... 


kent$ sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \1\n &/g" t.txt 

DROP TABLE IF EXISTS `orders` 
CREATE TABLE `orders` 
... 

DROP TABLE IF EXISTS `foo` 
CREATE TABLE `foo` 
... 
... 

DROP TABLE IF EXISTS `bar` 
CREATE TABLE `bar` 
... 
+0

Grazie, questo è un eccellente esempio chiaro. –