Utilisation de sed pour supprimer à la fois un crochet carré d'ouverture et de fermeture autour d'une chaîne

18

J'exécute cette commande dans un shell bash sur Ubuntu 12.04.1 LTS. J'essaie de supprimer à la fois les caractères [et les ]caractères d'un seul coup, c'est-à-dire sans avoir à piper pour séduire une deuxième fois.

Je sais que les crochets ont une signification particulière dans une expression régulière, je les échappe donc en ajoutant une barre oblique inverse. Le résultat que j'attendais est juste la chaîne 123mais les crochets restent et j'aimerais savoir pourquoi!

~$ echo '[123]' | sed 's/[\[\]]//'
[123]
Xhantar
la source
Ce que j'essaie de réaliser, c'est d'attribuer ce qui se trouve entre les crochets à une variable bash pour l'utiliser ailleurs dans mon script bash, donc s'il y a une meilleure façon d'y parvenir (en utilisant awk, peut-être?), Veuillez me le faire savoir .
Xhantar
2
Ajout d'un commentaire: vous pouvez utiliser la fonction PE de bash comme dans: str='[123]'; str1=${str/\[/}; str2=${str1/\]}; echo $str2
Valentin Bajrami
1
@ val0x00ff - Substitution bash pure .. merci! :) J'ai appris quelque chose de nouveau.
Xhantar

Réponses:

24

C'est facile, si vous suivez attentivement le manuel : tous les membres d'une classe de personnages perdent une signification particulière (à quelques exceptions près). Et] perd sa signification particulière s'il est placé en premier dans la liste. Essayer:

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

Cela dit:

  1. à l'intérieur des [crochets] extérieurs , remplacez l'un des caractères inclus, à savoir:
    • ] et
    • [
  2. remplacer l'un d'eux par la chaîne vide - d'où la chaîne de remplacement vide //,
  3. remplacez-les partout ( globalement ) - d'où la finale g.

Encore une fois, ] doit être le premier de la classe chaque fois qu'il est inclus.

Saparagus
la source
11

Je ne sais pas pourquoi cela ne fonctionne pas, mais cela fonctionne:

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

ou ca:

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

Vous pouvez également essayer une approche différente et faire correspondre la chaîne à l'intérieur des crochets (en supposant que la chaîne peut être mise en correspondance facilement et n'est pas définie par les crochets):

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

J'ai les mêmes problèmes avec votre regex d'origine, grepdonc je pense que ce n'est pas seulement une sedchose.

Bizarrement, ceux-ci produisent des résultats différents mais l'un d'eux correspond à ce que vous voulez:

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

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

Appliquer cela à votre original sed(et ajouter le /gmodificateur pour qu'il supprime les deux crochets):

echo '[123]' | sed 's/[][]//g'
123
Ladadadada
la source
Votre 3ème approche (egrep -o ...) ressemble à la solution la plus propre à mon problème. Je n'aurai que des entiers entre crochets (et désolé, j'aurais dû le mentionner dans ma question) donc je ne devrais pas rencontrer de bizarreries je pense. Merci!
Xhantar
3
Vous pouvez également utiliser tr: echo '[123]' | tr -d '[]'- évite les confusions de regexp sur l'échappement.
James O'Gorman
@James O'Gorman - Intéressant. Pour une raison quelconque, je pensais que cela trne pouvait traduire qu'un seul caractère à la fois, mais je me trompais. Merci!
Xhantar
4

Pour tout supprimer avant et après les crochets:

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

Si vos données sont comme ça, cela signifie toujours commencer et terminer par des crochets:

$ echo '[123]' | sed 's/.//;s/.$//;'
123
Gourou
la source
Les données avec lesquelles je travaille commenceront et se termineront toujours par un crochet carré oui. J'aimerais quand même savoir pourquoi ma solution ne fonctionnait pas. Des idées? Et existe-t-il un moyen de le faire sans spécifier 2x regex?
Xhantar
1
@Guru, cette solution a fonctionné de moi, et comme pour Xhantar, c'est une réponse très tardive, mais ce que je peux voir dans votre code et le guide Bash Beginners sur tldp.org, vous essayez de faire plusieurs recherches et remplacements, un pour '[' et l'autre pour ']' qui ne fonctionneront pas, pour espacer deux recherches différentes et les remplacer, utilisez le ";" ou les options -e. 's / <search> / <replace> / g; s / <search> / <replace> / g 'OR sed -e' s / <search> / <replace> / g '-e' s / <search> / <replace> / g '
ArunMKumar
1

Si vous avez une chaîne plus complexe comme 'abcdef [123] ghijk', vous pouvez également utiliser la commande bash interne 'cut' pour extraire le texte uniquement entre crochets:

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

Vous pouvez échapper au support d'ouverture à l'aide de \[. Pour le support de fermeture, utilisez []].

user2428118
la source