2009-11-21 6 views

Répondre

2

Vous pouvez l'utiliser dans sed:

sed -n /nch/,/kary/p $file 

Vous pouvez utiliser 'S2P' pour convertir en Perl.

Vous pouvez aussi écrire pur Perl:

while (<>) 
{ 
    next unless /nch/; 
    print; 
    while (<>) 
    { 
     print; 
     last if /kary/; 
    } 
} 

strictement, ces deux solutions imprimer chaque ensemble de lignes de 'NCH' à 'Kary'; Si 'nch' apparaît plus d'une fois, il imprime plus d'un morceau de code. Il est facile de corriger cela, surtout dans la pure Perl (solution «sed» laissée comme un exercice pour le lecteur).

OUTER: 
while (<>) 
{ 
    next unless /nch/; 
    print; 
    while (<>) 
    { 
     print; 
     last OUTER if /kary/; 
    } 
} 

En outre, les solutions recherchent « NCH » et « Kary » dans le cadre de la ligne - non pas pour la ligne. Si vous avez besoin d'eux pour correspondre à la ligne entière, utilisez '/^nch$/' etc comme regex.

+0

en utilisant 2 tandis que les boucles ne sont pas nécessaires, est-il? – ghostdog74

+0

Cela dépend si vous voulez utiliser des variables autres que '$ _'.Si vous utilisez une variable (comme dans la solution de Hairy Jock), alors non, la double boucle n'est pas nécessaire. Si vous le faites sans variables supplémentaires, la deuxième boucle prend la place de la variable d'état. –

+1

Il ya un perl direct oneliner équivalent à votre exemple awk: 'perl -ne 'imprimer si/foo /../bar /' – hobbs

0

Quelque chose comme:

$filter = 0; 
while (<>) { 
    chomp; 
    $filter = 1 if (! $filter && /^nch$/); 
    $filter = 0 if ($filter && /^ban$/); 
    print($_, "\n") if ($filter); 
} 

devrait fonctionner.

+0

Le chomp n'est pas strictement nécessaire, et ne pas chomping simplifie l'impression. En outre, il n'est pas clair pourquoi vous avez choisi «interdire» quand la question pose des questions sur «kary»; cela pourrait être considéré comme faisant des hypothèses injustifiées sur la disposition des données. –

+2

Le "chomp" permet de faire correspondre toute la ligne -/nch/ou/ban/est tout simplement trop permissif quand les grinches ou les banshees arrivent. –

+3

Le 'chomp' n'est pas nécessaire pour que les correspondances '/^nch $ /' fonctionnent. Et vous faites ce que la question demande: 'my $ filter = 0; while (<>) { \t $ filter = 1 if (! $ Filtre &&/^ nch $ /); \t imprime si ($ filtre); \t $ filter = 0 if ($ filtre &&/^ kary $ /); } '. Notez le repositionnement de l'impression et le test de 'kary'. –

0

si vous ne souhaitez que lire un bloc, dans gawk

gawk '/kary/&&f{print;exit}/nch/{f=1}f' file 

en Perl

perl -lne '$f && /kary/ && print && exit;$f=1 if/nch/; $f && print' file 

ou

while (<>) { 
    chomp; 
    if ($f && /kary/) { 
     print $_."\n"; 
     last; 
    } 
    if (/nch/) { $f = 1; } 
    print $_ ."\n" if $f; 
} 
+0

Les scripts Perl et Awk impriment kary et se terminent s'ils apparaissent avant le premier nch - qui ne fait pas partie de la spécification. –

+0

corrigé. Astuce pour signaler – ghostdog74

7

Si je comprends bien votre question, cela est assez simple .

#!perl -w 
    use strict; 
    use autodie; 

    open my $in,'<',"File1.txt"; 
    open my $out,'>',"File2.txt"; 

    while(<$in>){ 
    print $out $_ if /^nch/ .. /^kary/; 
    } 
+5

aussi: $ perl -lne 'imprimer si /nch/../kary/' file> output – ghostdog74

+0

L'option '-l' n'est pas nécessaire, mais le one-liner fonctionne bien comme une simplification du script de Mike . Un programme qui construit des noms de fichiers dans ce genre n'est pas un programme général, Mike. –

+2

Encore, +1 pour l'utilisation de la notation de plage. –

3

De la réponse de perlfaq6 à How can I pull out lines between two patterns that are themselves on different lines?


Vous pouvez utiliser un peu exotique .. opérateur de Perl (documenté dans perlop):

perl -ne 'print if /START/ .. /END/' file1 file2 ... 

Si vous voulez du texte et non les lignes , vous utiliseriez

perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ... 

Toutefois, si vous souhaitez que les occurrences imbriquées de START dans END soient appliquées, vous rencontrerez le problème décrit dans la question de cette section sur la correspondance du texte équilibré.

Voici un autre exemple d'utilisation ..:

while (<>) { 
    $in_header = 1 .. /^$/; 
    $in_body = /^$/ .. eof; 
# now choose between them 
} continue { 
    $. = 0 if eof; # fix $. 
} 
Questions connexes