Amélio regex (ruby)

Hello !

Pour un exercice, je récupère des strings tous pourris genre :

bout\n\n\n\n\n\n\n\n\ntruc Machin chose\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,025\n\nPatings
bout\n\n\n\n\n\n\n\n\nBidule jaune Verdatre\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,422\n\nPatings

Le but est d’isoler les trois mots du milieu.

J’ai trouvé ceci (?<=\\n)(\D*?)(?=\\n)

Y aurait-il mieux ?

Bien que tu ne précises pas comment tu l’utilises, avec quelle commande, si tu en es satisfait, c’est sûrement très bien. Un bout de regex seul n’est pas vraiment exploitable.

Les trois mots sont « truc Machin chose ».

Et ici, « Bidule jaune Verdatre ».

Hello ! Merci pour votre attention :slight_smile:

Comme indiqué dans le premier post, ce sont bien seulement les mots du milieu (ici 3, mais possiblement plus ou moins), bien cachés par des cochonneries et des sauts de ligne qui les entourent que je veux isoler.

Ils seront ensuite transformé en string cohérent en ruby (probablement avec la méthode #gsub) pour être exploités.

Euhh, je ne sais trop comment le dire plus clairement qu’au premier post :confused:

Le but est d’isoler les groupes de mots au milieu des longues chaines comme dans les exemples.
Les mots du début et de la fin sont exclus.
J’avais donné deux exemples, j’en donne trois pour préciser.

bout\n\n\n\n\n\n\n\n\n**truc Machin chose**\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,025\n\nPatings
bout\n\n\n\n\n\n\n\n\n**Bidule jaune Verdatre**\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,422\n\nPatings
bout\n\n\n\n\n\n\n\n\n**la cantrice Chauve aphone**\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,355\n\nPatings

Une fois récupérés, je pourrai les traiter comme string dans ruby pour les classer, les analyser, les retraiter, etc…

Manifestement la source de ces chaînes de caractères est un fichier plein de sauts de lignes qui a été récupéré un peu à la sauvage, mais ce n’est pas l’objet de la réflexion : ce qui est fourni c’est ça.

On va supposer que tu as un gros souci avec les retours de ligne (confirmé maintenant), et que les lignes de ton fichier ne soient pas coupées en morceaux:

bout\n\n\n\n\n\n\n\n\nla cantrice Chauve aphone\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,355\n\nPatings

Dans cet exemple, tu voudrais extraire juste ‹ la cantrice Chauve aphone ›, la deuxième chaîne de mots:

$ X='bout\n\n\n\n\n\n\n\n\nla cantrice Chauve aphone\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n1,355\n\nPatings'
$ printf "$X" |grep . |sed -n 2p
la cantrice Chauve aphone

Ah, super, tu as compris, maintenant, je pense que le but est de faire ça avec des regex.
@nam1962, peux-tu nous préciser avec quoi tu vas interpréter ce regex ? Dis-nous aussi s’il est très important que ça se fasse avec des regex ou si la proposition de @Verner fera l’affaire.

Hello !

Effectivement, il a fallu longtemps, mais le but a été compris.
Sauf que ce n’est pas une soluce bash qui est recherchée, mais une soluce utilisable par ruby en l’occurence, (mais un autre langage aussi potentiellement).

Donc comme l’indique le titre et comme tu le rappelles, ma recherche est bien d’isoler ces mots avec juste une regex :slight_smile:

@nam1962
Pour ton information, quand on n’a pas un écran 32’’, toutes les lignes que tu avais postées comme exemples, maintenant corrigées, paraissaient en fait sur deux lignes à l’écran.
Impossible d’affirmer ou extrapoler si cette coupure est interne à ton fichier vérolé, ou à une difficulté à poster une longue ligne sur un forum, sans casser la ligne, ce qui explique les difficultés de formulation précise de recherche.

Pour ceux qui voudraient t’aider avec « ruby », je poste un fichier avec les lignes correctes, ce sera plus simple, plus clair et exploitable, sans contorsion.

ftest.txt (308 Octets)

En résumé, tu souhaites extraire la ‹ deuxième chaîne de X mots séparés par des espaces ›, de toutes les lignes d’un fichier, et qui commencent par ‹ bout ›, et se terminent par ‹ Patings ›, sans aucune ambiguïté ou autre surprise.
Seul toi peut confirmer cette hypothèse pour garantir la fiabilité d’un résultat.

Tu as proposé ce regex (?<=\\n)(\D*?)(?=\\n) que personne n’a pu tester dans ‹ ruby › pour le moment.
Quel résultat obtiens-tu dans ruby ? Es-tu satisfait du résultat ?
EDIT: testé, c’est pas bon du tout.
――――――――――――――――――――――――――
Toujours pas d’amateur de ‹ ruby-regex › dans ce sujet ? Rien de surprenant, statistiquement parlant.
Le ruby-regex est encore une autre variante de regex parmi les dizaines existantes, et est incompatible avec le regex Linux:
• BRE - Basic Regular Expression engine (POSIX)
• ERE - Extended Regular Expression engine.

Jongler d’une version regex exotique à une autre est plein de pièges, et c’est un exercice moyennement intéressant, voir pas du tout.

Si quelqu’un s’intéresse au ruby-regex pour aider nam1962, il peut essayer ici:
Rubular: a Ruby regular expression editor

Si au bout d’un certain temps, personne ne trouve, pas de panique, le bon vieux sed avec du vrai regex fera l’affaire pour nettoyer ce fichier.

$ sed 's:[^\]*\(\\n\)\+::;s:\\n.*::' ftest.txt
  Bidule jaune Verdatre
  la cantatrice chauve aphone
  truc Machin chose
  le ruby regex
  est non standard

Bon courage.

Merci pour ton attention.
Effectivement, Rubular n’était pas content.

Étonné de voir ma question considérée comme imprécise, je l’ai posée, quasi exactement idem, sur un autre fofo de distro.
La question n’est donc pas si obscure, car la réponse est arrivée illico :

(?<=\\n)([a-zA-Z ]+?)(?=\\)

Fait donc bien le boulot en absolu comme en relatif :wink:

Sur le forum manjaro, la balise code ne tronçonne pas les lignes en fonction de la largeur de l’écran contrairement à ici, causant l’incohérence entre la demande et les lignes supposées extraites d’un fichier vérolé. Pour ne pas couper les lignes ici, la balise code ne suffit pas, il faut placer le texte entre « ``` »

 >> ---- début de longue ligne sans troncature  >>----------------------------------------------------------------------fin <<

80% des messages de ce forum sont ré-édités pour ce genre de problème.

Grep comprend trois types de regex: BRE (par défaut) + ERE (étendu /-E) et Perl (-P).
Le regex Perl de grep comprend les deux syntaxes:

X='bout\n\n\ntruc Machin chose\n\n\n\n1,025\n\nPatings'

$ echo "$X" |grep -Po '(?<=\\n)(\D*?)(?=\\n)'
  truc Machin chose

$ echo "$X" |grep -Po '(?<=\\n)([a-zA-Z ]+?)(?=\\)'
  truc Machin chose

Kate interprète aussi correctement les deux syntaxes:

ksnip_20230309-213735-1

ksnip_20230309-213932-2

J’ai constaté que certaines syntaxes regex extrêmement simples ne fonctionnent pas pour du regex ruby: pas compris.
Il ne faut pas chercher de logique à ce regex exotique, mais le bon réflexe est effectivement de se rapprocher au maximum d’un regex POSIX, d’un dénominateur commun de dizaines de regex qui traînent dans la nature.
On va dire que ce sont les mystères des regex exotiques, d’où l’importance de toujours préciser le type précis de regex recherché, dès le premier message (le titre du sujet a été corrigé en conséquence), quand ce n’est pas du regex linux, qu’il soit BRE, ERE ou Perl.

1 J'aime

Merci pour cet éclairage.

C’est vrai que c’est ballot, j’avais uniquement mis un backtick au lieu de trois et en plus, sur mon écran, tout apparaît correct !

Le diable se cache dans les détails !

Pour Ruby, c’est très intéressant pour moi : décrassage (j’étais resté… au basic !) et apprentissage de pas mal de principes.