# Commande sed / extraire un bloc texte commençant par ###

**URL:** <https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991>\
**Category:** Programmation\
**Created:** [Mars 17, 2017, 2:38 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991 "2017-03-17T14:38:45Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 17, 2017, 2:38 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/1 "2017-03-17T14:38:46Z")

</div>

Salut à tous,

Ma question est relativement simple, j’ai besoin d’extraire une partie du fichier “grub.cfg” et je suis entrain de peiner avec la commande “sed”, à savoir que je n’arrive pas à comprendre quelle est la syntaxe exacte pour lui dire d’extraire la portion de texte du fichier “grub.cfg” entre :

```
### BEGIN /etc/grub.d/10_linux

### END /etc/grub.d/10_linux

```

LE problème est dans l’interprétation des caractères dièze du début de lignes, je ne sais pas comment faire passer ça comme bloc texte dans :

`$ sed -n '/### BEGIN /etc/grub.d/10_linux/,/### END /etc/grub.d/10_linux/p'`

Bien sûr cette expression n’est pas bonne et je vous passe tous les essais que j’ai fait… 😂

---

<div class="post-metadata">

**Author:** ![dindoun](https://www.debian-fr.org/user_avatar/www.debian-fr.org/dindoun/32/4281_2.png) [@dindoun](https://www.debian-fr.org/u/dindoun)\
**Post date:** [Mars 17, 2017, 3:12 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/2 "2017-03-17T15:12:43Z")

</div>

salut  
t’as essayé `\#` ?

---

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 17, 2017, 3:14 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/3 "2017-03-17T15:14:07Z")

</div>

Oui, je pense que ça ne marche pas à cause des trois caractères dièze et non pas un… 😕

---

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 17, 2017, 3:34 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/4 "2017-03-17T15:34:49Z")

</div>

Bon j’ai trouvé un workaround à l’expression ci-dessus qui a l’air de fonctionner, en réduisant simplement l’expression :

> [@GOGI](#):
>
> $ sed -n ‹&nbsp;/### BEGIN /etc/grub.d/10\_linux/,/### END /etc/grub.d/10\_linux/p&nbsp;›

à :

`$ sed -n '/10_linux/,/10_linux/p' grub.cfg`

où «&nbsp;sed&nbsp;» va chercher la première occurence de l’expression «&nbsp;10\_linux&nbsp;», puis la deuxième… Donc effectivement ça marche mais si quelqu’un peut me répondre quand même pourquoi la 1ère ne marche pas, enfin ce qu’il manque, je suis preneur quand même… 🙂

---

<div class="post-metadata">

**Author:** ![Sputnik93](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/s/35a633/32.png) [@Sputnik93](https://www.debian-fr.org/u/Sputnik93)\
**Post date:** [Mars 17, 2017, 4:29 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/5 "2017-03-17T16:29:03Z")

</div>

ça ne viendrait pas plutôt du fait que /### BEGIN /etc/grub.d/10\_linux/ et /### END /etc/grub.d/10\_linux/ contiennent des / (à cause des chemins d’accès) qui sont sensés servir de séparateur ? Tu as essayé en échappant les / ? ou en utilisant un autre caractère comme séparateur ?

---

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 17, 2017, 6:27 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/6 "2017-03-17T18:27:25Z")

</div>

> [@Sputnik93](#):
>
> ça ne viendrait pas plutôt du fait que /### BEGIN /etc/grub.d/10\_linux/ et /### END /etc/grub.d/10\_linux/ contiennent des / (à cause des chemins d’accès) qui sont sensés servir de séparateur ? Tu as essayé en échappant les / ? ou en utilisant un autre caractère comme séparateur ?

Effectivement maintenant que tu le dis il y a de grandes chances que ce soit ça, mais alors comment faire pour passer le tout comme un bloc texte à sed, par exemple {### BEGIN /etc/grub.d/10\_linux}.  
J’y connais rien à sed.

---

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 17, 2017, 6:49 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/7 "2017-03-17T18:49:43Z")

</div>

Ok, j’ai trouvé la bonne expression, tu avais vu juste il fallait échapper les “/” un à un… Bien joué 😉

Donc la bonne expression est :

```
$ sed -n '/### BEGIN \/etc\/grub.d\/10_linux ###/,/### END \/etc\/grub.d\/10_linux ###/p' /chemin/vers/le/fichier/grub.cfg
```

---

<div class="post-metadata">

**Author:** ![Sputnik93](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/s/35a633/32.png) [@Sputnik93](https://www.debian-fr.org/u/Sputnik93)\
**Post date:** [Mars 20, 2017, 1:05 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/8 "2017-03-20T13:05:26Z")

</div>

Sinon pour ce cas de figure, je sais qu’avec la commande de substitution de sed (‘s/motif1/motif2/’) on peut mettre ce qu’on veut comme caractère de séparation (tant que ce n’est pas un caractère interprété), par exemple `sed 's|motif1|motif2|' fichier`, ce qui est plutôt pratique quand les motifs contiennent de nombreux caractères interprétés.

Mais ça n’a pas l’air de fonctionner en dehors de l’utilisation de la commande de substitution.  
Eventuellement, tu pourrais utiliser des groupes de capture pour faire ce que tu veux en utilisant la substitution:  
`sed 's|(### BEGIN /etc/grub.d/10_linux)(.*)(### END /etc/grub.d/10_linux)|\2|'`  
=\> /### BEGIN /etc/grub.d/10\_linux/ va constituer le groupe de capture \1  
=\> ### END /etc/grub.d/10\_linux va constituer le groupe \3  
=\> tout ce qu’il y a entre les deux constituera le groupe \2  
=\> on remplace le tout par le groupe \2  
Je n’ai pas testé (suis au boulot ☹ ) mais c’est l’idée.

---

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 20, 2017, 2:31 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/9 "2017-03-20T14:31:32Z")

</div>

> [@Sputnik93](#):
>
> Eventuellement, tu pourrais utiliser des groupes de capture pour faire ce que tu veux en utilisant la substitution:
> 
> $ sed ‹&nbsp;s|(### BEGIN /etc/grub.d/10\_linux)(.\*)(### END /etc/grub.d/10\_linux)|\2|&nbsp;›

Ça ne marche pas, voci ce que me renvoie la commande :

`sed: -e expression n°1, caractère 72: référence \2 invalide dans le côté droit de la commande `s’`

---

<div class="post-metadata">

**Author:** ![anon29980398](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/f4b2a3/32.png) [@anon29980398](https://www.debian-fr.org/u/anon29980398)\
**Post date:** [Mars 20, 2017, 3:40 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/10 "2017-03-20T15:40:55Z")

</div>

Bonjour

Il faut juste “échapper” le premier caractère de séparation de chacun des motifs :

```bash
sed -n '\|### BEGIN /etc/grub.d/10_linux ###|,\|### END /etc/grub.d/10_linux ###|p' /boot/grub/grub.cfg

```

ou bien, si on voulait être plus strict :

```bash
sed -n '\|^### BEGIN /etc/grub.d/10_linux ###$|,\|^### END /etc/grub.d/10_linux ###$|p' /boot/grub/grub.cfg

```

* * *

Sans les motifs :

```bash
sed -n '\|^### BEGIN /etc/grub.d/10_linux ###$|,\|^### END /etc/grub.d/10_linux ###$|{//!p}' /boot/grub/grub.cfg 

```

---

<div class="post-metadata">

**Author:** ![Sputnik93](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/s/35a633/32.png) [@Sputnik93](https://www.debian-fr.org/u/Sputnik93)\
**Post date:** [Mars 20, 2017, 3:56 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/11 "2017-03-20T15:56:41Z")

</div>

> [@GOGI](#):
>
> Ça ne marche pas, voci ce que me renvoie la commande :
> 
> sed: -e expression n°1, caractère 72: référence \2 invalide dans le côté droit de la commandes’`

Ah oui exact, sed utilise Basic Regular Expressions, donc il faut utiliser \( et \) pour faire des groupes de capture, ou bien passer l’option -r (pour regex-extended).  
Mais la solution de MicP est mieux.

---

<div class="post-metadata">

**Author:** ![GOGI](https://www.debian-fr.org/user_avatar/www.debian-fr.org/gogi/32/3836_2.png) [@GOGI](https://www.debian-fr.org/u/GOGI)\
**Post date:** [Mars 20, 2017, 5:42 UTC](https://www.debian-fr.org/t/commande-sed-extraire-un-bloc-texte-commencant-par/72991/12 "2017-03-20T17:42:55Z")

</div>

> [@anon29980398](#):
>
> Sans les motifs :
> 
> sed -n ‹&nbsp;|^### BEGIN /etc/grub.d/10\_linux ###$|,|^### END /etc/grub.d/10\_linux ###$|{//!p}&nbsp;› /boot/grub/grub.cfg

Merci @anon29980398, c’est la bonne solution finale, notamment pour la lecture de l’expression au sein du script, plutot que d’avoir des caractères d’échappement à chaque fois.

> [@Sputnik93](#):
>
> Ah oui exact, sed utilise Basic Regular Expressions, donc il faut utiliser ( et ) pour faire des groupes de capture, ou bien passer l’option -r (pour regex-extended).Mais la solution de MicP est mieux.

oui c’est une question de syntaxe et c’est ma faiblesse car je n’y connais rien.

En tous cas merci à tous les deux. 😉
