Usando sed per rimuovere una parentesi quadra aperta e chiusa attorno a una corda


18

Sto eseguendo questo comando in una shell bash su Ubuntu 12.04.1 LTS. Sto tentando di rimuovere sia la [e ]caratteri in un colpo solo, cioè senza dover tubo sed una seconda volta.

So che le parentesi quadre hanno un significato speciale in una regex, quindi le sto sfuggendo anticipando con una barra rovesciata. Il risultato che mi aspettavo è solo la stringa 123ma rimangono le parentesi quadre e mi piacerebbe sapere perché!

~$ echo '[123]' | sed 's/[\[\]]//'
[123]

Quello che sto cercando di ottenere alla fine è quello di assegnare qualsiasi cosa tra parentesi quadre a una variabile bash da usare altrove nel mio script bash, quindi se c'è un modo migliore per farlo (usando awk, forse?), Per favore fatemi sapere .
Xhantar,

2
Basta aggiungere come commento: puoi usare la funzione PE di bash come in: str='[123]'; str1=${str/\[/}; str2=${str1/\]}; echo $str2
Valentin Bajrami,

1
@ val0x00ff - Sostituzione bash pura .. grazie! :) Ho imparato qualcosa di nuovo.
Xhantar,

Risposte:


24

Questo è facile se segui attentamente il manuale : tutti i membri all'interno di una classe di caratteri perdono un significato speciale (con poche eccezioni). E] perde il suo significato speciale se viene inserito per primo nell'elenco. Provare:

$ echo '[123]' | sed 's/[][]//g'
123
$

Questo dice:

  1. all'interno delle [parentesi] esterne , sostituisci uno qualsiasi dei caratteri inclusi, vale a dire:
    • ] e
    • [
  2. sostituisci uno di essi con la stringa vuota, quindi la stringa di sostituzione vuota //,
  3. sostituirli ovunque (a livello globale ) - da qui la finale g.

Ancora una volta, ] deve essere il primo nella classe ogni volta che è incluso.


11

Non sono sicuro del motivo per cui ciò non funziona ma questo funziona:

echo '[123]' | sed 's/\(\[\|\]\)//g'

o questo:

echo '[123]' | sed -r 's/(\[|\])//g'

Puoi anche provare un approccio diverso e abbinare la stringa tra parentesi (supponendo che la stringa possa essere facilmente abbinata e non sia definita dalle parentesi):

echo '[123]' | egrep -o "[0-9]+"

Sto avendo gli stessi problemi con il tuo regex originale usando grepquindi sospetto che questo non sia solo una sedcosa.

Stranamente, questi producono risultati diversi ma uno di questi corrisponde a quello che vuoi:

echo '[123]' | egrep -o '[^][]+'
123

echo '[123]' | egrep -o '[^[]]+'
3]

Applicando questo al tuo originale sed(e aggiungendo il /gmodificatore in modo da rimuovere entrambe le parentesi):

echo '[123]' | sed 's/[][]//g'
123

Il tuo terzo approccio (egrep -o ...) sembra la soluzione più pulita al mio problema. Avrò solo numeri interi tra parentesi quadre (e mi dispiace, avrei dovuto menzionarlo nella mia domanda), quindi non dovrei imbattermi in stranezze che penso. Grazie!
Xhantar,

3
Puoi anche usare tr: echo '[123]' | tr -d '[]'- evita le confusioni di regexp sull'evasione.
James O'Gorman,

@James O'Gorman - Interessante. Per qualche ragione ho pensato che trpotesse tradurre solo un massimo di caratteri alla volta, ma mi sbagliavo. Grazie!
Xhantar,

4

Per rimuovere tutto prima e dopo le parentesi quadre:

$ echo '[123]' | sed 's/.*\[//;s/\].*//;'
123

Se i tuoi dati sono così, significa sempre iniziare e finire con parentesi quadre:

$ echo '[123]' | sed 's/.//;s/.$//;'
123

I dati con cui sto lavorando inizieranno e finiranno sempre con una parentesi quadra sì. Mi piacerebbe comunque sapere perché la mia soluzione non funzionava. Qualche idea? E c'è un modo per farlo senza specificare 2x regex?
Xhantar,

1
@Guru questa soluzione ha funzionato da me, e per quanto riguarda Xhantar, questa è una risposta molto tardiva, ma quello che posso vedere dal tuo codice e dalla guida Bash Beginners su tldp.org, stavi cercando di fare più ricerche e sostituire, una per '[' e l'altro per ']' che non funzioneranno, per distanziare due diverse ricerche e sostituire usare ";" o le opzioni -e. 's / <search> / <replace> / g; s / <search> / <replace> / g 'OR sed -e' s / <search> / <replace> / g '-e' s / <search> / <replace> / g '
ArunMKumar

1

Se hai una stringa più complessa come 'abcdef [123] ghijk' puoi anche usare il comando bash interno 'cut' per estrarre il testo solo tra parentesi quadre:

$ echo 'abcdef[123]ghijk' | cut -d '[' -f 2 | cut -d ']' -f 1
123

1

È possibile sfuggire alla staffa di apertura utilizzando \[. Per la staffa di chiusura, utilizzare []].

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.