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

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… :joy:

salut
t’as essayé \# ?

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

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

à :

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

où “sed” va chercher la première occurence de l’expression “10_linux”, 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… :slight_smile:

ç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.

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

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
1 J'aime

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 :frowning: ) mais c’est l’idée.

Ç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’`

Bonjour

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

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 :

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

Sans les motifs :

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

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.

Merci @MicP, 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.

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. :wink: