2011-11-10 5 views
4

Mon script lit dans de gros fichiers texte et saisit la première page avec une regex. Je dois supprimer les deux premières lignes de chaque première page ou modifier l'expression rationnelle pour correspondre à 1 ligne après la chaîne == Page 1 ==. J'inclus le script entier ici parce que j'ai demandé dans les questions du passé et parce que je suis nouveau à ruby ​​et je ne sais pas toujours comment intégrer des extraits de réponses:Supprimer les deux premières lignes du fichier avec ruby ​​

#!/usr/bin/env ruby -wKU 
require 'fileutils' 

source = File.open('list.txt') 
source.readlines.each do |line| 
    line.strip! 
    if File.exists? line 
    file = File.open(line) 
    end 

    text = (File.read(line)) 
    match = text.match(/==Page 1(.*)==Page 2==/m) 
    puts match 
end 
+0

Pourriez-vous exprimer ce que vous voulez que le code fasse? Cela me ressemble: Je veux supprimer les 2 premières lignes de chaque fichier inclus dans une liste stockée dans un autre fichier. Est-ce exact? – mliebelt

+0

Désolé - édité. Vous avez raison, vous voulez supprimer les deux premières lignes de chaque fichier dans ma liste. – chuckfinley

+0

J'ai mis à jour la réponse. J'espère avoir trouvé votre problème :-) _ (notifier par un commentaire, car je ne sais pas si les demandeurs sont informés des mises à jour des réponses) _ – Arsen7

Répondre

3

Maintenant, quand vous avez mis à jour votre question, j'ai dû supprimer une grande partie de si bonne réponse :-)

Je suppose que le point principal de votre problème était que vous vouliez utiliser match[1] au lieu de match. L'objet renvoyé par la méthode Regexp.match (MatchData) peut être traité comme un tableau, qui contient toute la chaîne correspondante comme premier élément et chaque sous-requête dans les éléments suivants. Donc, dans votre cas, la variable match(et match[0]) est la chaîne entière correspondance (avec « == == page .. ») marques, mais vous vouliez que le premier sous-expression qui est caché dans match[1].


Maintenant à propos d'autres problèmes mineurs que je sens dans votre code. S'il vous plaît, ne soyez pas offensé au cas où vous savez déjà ce que je dis, mais peut-être que d'autres bénéficieront des avertissements.

La première partie de votre code (if File.exists? line) a été vérifier si le fichier existe, mais votre code vient d'ouvrir le fichier (sans le fermer!) Et encore essayait d'ouvrir le fichier quelques lignes plus loin.

Vous pouvez utiliser cette ligne à la place:

next unless File.exists? line 

Le deuxième chose est que le programme devrait être prêt à gérer la situation lorsque le fichier n'a pas de marques de page, il ne correspond pas au modèle. (La match variables aurait alors nil)

La troisième suggestionest qu'un petit modèle plus complexe pourrait être utilisé. L'actuel (/==Page 1==(.*)==Page 2==/m) retournerait le contenu de la page avec la marque de fin de ligne comme premier caractère. Si vous utilisez ce modèle:

/==Page 1==\s*\n(.*)==Page 2==/m 

alors la sous-expression ne contiendra pas les espaces blancs placés dans la même ligne que le texte « == Page 1 ==`. Et si vous utilisez ce modèle:

/==Page 1==\s*\n(.*\n)==Page 2==/m 

alors vous serez sûr que la marque « == Page 2 == » commence dès le début de la ligne.

Et le quatrième problème est que très souvent les programmeurs (parfois moi y compris, bien sûr) ont tendance à oublier de fermer le dossier après ils l'ont ouvert. Dans votre cas, vous avez ouvert le fichier 'source', mais dans le code il n'y avait pas d'instruction source.close après la boucle.La façon la plus sûre de la gestion des fichiers est en passant un bloc à la méthode File.open, donc vous pouvez utiliser le formulaire suivant des premières lignes de votre programme:

File.open('list.txt') do |source| 
    source.readlines.each do |line| 

... mais dans ce cas, il serait plus propre juste écrire:

File.readlines('list.txt').each do |line| 

en prenant tout cela, le code pourrait ressembler à ceci (j'ai changé la line variable fname pour une meilleure lisibilité du code):

#!/usr/bin/env ruby -wKU 
require 'fileutils' 

File.readlines('list.txt').each do |fname| 
    fname.strip! 
    next unless File.exists? fname 

    text = File.read(fname) 
    if match = text.match(/==Page 1==\s*\n(.*\n)==Page 2==/m) 
    # The whole 'page' (String): 
    puts match[1].inspect 
    # The 'page' without the first two lines: 
    # (in case you really wanted to delete lines): 
    puts match[1].split("\n")[2..-1].inspect 
    else 
    # What to do if the file does not match the pattern? 
    raise "The file #{fname} does NOT include the page separators." 
    end 
end 
Questions connexes