2009-03-23 10 views
3

J'ai un tas de fichiers qui contiennent un en-tête semi-standard. C'est-à-dire que le look est très similaire mais le texte change quelque peu.Comment puis-je supprimer du texte au début d'un fichier en utilisant une regex?

Je souhaite supprimer cet en-tête de tous les fichiers.

regardant les fichiers, je sais que ce que je veux supprimer est encapsulé entre des mots similaires.

Ainsi, par exemple, j'ai:

Foo bar...some text here... 
more text 
Foo bar...I want to keep everything after this point 

J'ai essayé cette commande en Perl:

perl -pi -e "s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt 

Mais cela ne fonctionne pas. Je ne suis pas un expert, mais regex espérant que quelqu'un sait comment supprimer fondamentalement un morceau de texte à partir du début d'un fichier basé sur une correspondance de texte et non le nombre de caractères ...

Répondre

7

Par défaut, ARGV (alias <> qui est utilisé dans les coulisses par -p) ne lit qu'une seule ligne à la fois.

Solutions:

  1. serties $/, qui indique à Perl de lire un fichier entier à la fois.

    perl -pi -e "BEGIN{undef$/}s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt 
    

    BEGIN est nécessaire d'avoir ce code exécuté avant la première lecture est faite.

  2. Utilisez -0, qui définit $/ = "\0".

    perl -pi -0 -e "s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt 
    
  3. Profitez de l'flip-flop operator.

    perl -ni -e "print unless 1 ... /^Foo.bar/' 
    

    Ceci évitera l'impression à partir de la ligne 1 vers /^Foo.bar/.

+0

-0 n'est pas aussi sûr que -0777 qui est garanti pour mettre perl en mode slurp. –

+0

Ce n'est dangereux que sur les données binaires. On espère que * .txt sont en fait des fichiers texte. – ephemient

+0

Essayé tous les trois. Dernier: perl -ni -e "print sauf 1 ... /^Project.Gutenberg/" 00ws110.txt - ne fonctionne toujours pas. Il n'imprime rien. – GeoffreyF67

0

Ici vous allez! Cela remplace la première ligne du fichier:


use Tie::File; 

tie my @array,"Tie::File","path_to_file" or die("can't tie the file"); 
$array[0] =~s/text_i_want_to_replace/replacement_text/gi; 
untie @array; 

Vous pouvez utiliser le tableau et vous verrez les modifications du tableau. Vous pouvez supprimer des éléments du tableau et effacera la ligne du fichier. L'application de substitution sur les éléments remplacera le texte des lignes.

Si vous voulez supprimer les deux premières lignes, et garder quelque chose à partir du troisième, vous pouvez faire quelque chose comme ceci:


# tie the @array before this 
shift @array; 
shift @array; 
$array[0]=~s/foo bar\.\.\.//gi; 
# untie the @array 

et cela fera exactement ce dont vous avez besoin!

3

Si votre en-tête s'étend sur plus d'une ligne, vous devez indiquer à perl combien il faut lire.Si les fichiers sont de petite taille par rapport à la mémoire, vous voudrez peut-être juste slurp le fichier en mémoire:

perl -0777pi.orig -e 's/your regex/your replace/s' file1 file2 file3 

L'option -0777 définit perl en mode slurp, donc $_ tiendra le chaque fichier entier chaque fois dans la boucle . Aussi, n'oubliez pas de définir l'extension de sauvegarde. Si vous ne le faites pas, vous pouvez constater que vous avez effacé vos données accidentellement et n'avez aucun moyen de le récupérer. Voir perldoc perlrun pour plus d'informations. Compte tenu des informations contenues dans les commentaires, il semble que vous essayez de dépouiller toutes les choses ennuyeuses de l'avant d'un ebook Project Gutenberg. Si vous comprenez toutes les questions de droit d'auteur en cause, vous devriez être en mesure de se débarrasser de la question avant comme celui-ci:

perl -ni.orig -e 'print unless 1 .. /^\*END/' 00ws110.txt 

L'en-tête du projet Gutenberg se termine par

*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END* 

Un plus sûr regex prendrait en compte le *END* à la fin de la ligne, mais je suis paresseux.

2

je pourrais être mal interpréter ce que vous demandez, mais il me semble aussi simple que cela:

perl -ni -e 'print unless 1..($. > 1 && /^Foo bar/)' 
+0

Ou simplement utiliser '1 .../^ Foo bar /' (remarquez: triple point, pas double) au lieu de tester '$ .'. – ephemient

Questions connexes