Je dois rarement faire face à des scripts, donc je suis contre un manque de connaissances pour ce problème.
J'ai un fichier> 500 Mo dans le texte, qui est joliment sectionné, mais je sais qu'il y en a 5 à 10 "mauvais" sections à l'intérieur. Les données des sections peuvent être évaluées assez facilement par un humain, je ne sais pas comment le faire dans un programme. P>
Je prends une bonne valeur connue dans Un exemple de deux sections dans le fichier ressemble à ceci. Le premier est "mauvais" et la seconde est "bonne". P> Sections Démarrez et finillez logiquement, avec si si Remarque - clarification de Je crois que cela peut être fait dans Awk ou Perl, je peux faire des doublures très simples, mais cela dépasse mes compétences. P> P> #field myfield Code> - Toutefois, si cette valeur n'apparique pas dans
#field emplacement code>, quelque chose s'est mal passé. p>
#start code> et
#end code> p> li>
#field emplacement code> n'existe pas, allez à la section suivante p> li>
#field myfield = "bar" code> et
#field emplacement code> ne contient pas
bar code>, imprimer toutes les lignes de cette section à un nouveau fichier. P> li>
#field myfield = "bar" code> - Ceci est une valeur de contrôle I mis en saisissant d'autres informations sur les données car ce fichier est en construction (dans mon cas C'est un indicateur de langue, tel que FR ou DE. de sorte qu'il serait littéralement
#field myfield = "fr" code> toute autre valeur de ce champ serait ignoré, ce n'est pas un enregistrement qui correspond à mon Critères. P> LI>
ol>
4 Réponses :
Vous pouvez faire quelque chose comme ci-dessous. C'est juste un brouillon, mais cela fonctionnera avec vos échantillons de données. Utilisez opérateur de bascule pour trouver le début et la fin des enregistrements. Utilisez un hachage pour stocker les valeurs de champ et une matrice pour stocker l'enregistrement.
Je vérifie simplement si la valeur est dans la chaîne d'emplacement, vous pouvez souhaiter réduire davantage la vérification en vous assurant qu'il est dans le bon endroit ou le bon cas. P>
use strict; use warnings; my @record; my %f; while(<DATA>) { if (/^#START / .. /^#END */) { if (/^#START /) { @record = (); # reset %f = (); } push @record, $_; if (/^#END */) { # check and print if ($f{'LOCATION'} !~ /$f{'MyField'}/) { print @record; } } else { # add fields to hash if (/^#FIELD (.+)/) { # use split with limit of 2 fields my ($key, $val) = split /=/, $1, 2; next unless $val; # no empty values $val =~ s/^"|"$//g; # strip quotes $f{$key} = $val; } } } } __DATA__ #START Descriptor #FIELD LOCATION="http://path.to/file/here&Value=FOO&OtherValue=BLAH" #FIELD AnythingElse #FIELD MyField="BAR" #END #START Descriptor #FIELD LOCATION=http://path.to/file/here&Value=BAR&OtherValue=BLAH" #FIELD AnythingElse #FIELD MyField="BAR" #END
C'était bien commenté et utile pour moi comme le questionneur. C'est très cool que j'ai à la fois une réponse "courte" et une réponse "longue". Merci! (Je joue avec ces suggestions maintenant!)
one-liner:
perl -ne 'BEGIN { $/ = "#END\n" }' -e '/MyField="(.*?)"/; print if !/Value=$1/' <file >newfile
Imprimer $ _ n'est pas nécessaire, $ _ est la variable par défaut, impression devrait suffire
Fichier> Newfile CODE> fonctionnerait aussi bien que
$ argv code>
obtenir au nom du fichier d'entrée.
Set Séparateur d'enregistrement d'entrée sur #end \ n code > et lire directement des enregistrements:
Dans le 2e enregistrement, où Myfield = bar et emplacement comprennent une barre, c'est un enregistrement OK, mes opérations ont réussi. L'enregistrement préalable, où la barre n'apparaît pas à l'emplacement était l'erreur. Il me dit que j'avais un problème pour analyser le fichier à cet endroit. Je veux seulement lire les segments qui ont eu un problème.
Voici un petit gawk code> one-liner pour vous -
[jaypal:~/Temp] gawk '
{
if ($2!~/^#FIELD LOCATION/)
{
next;
}
else
{
split($2,ary,"=|&");
split($4,ary1,"=|\"");
if(ary[4]!=ary1[3])
{
print $0 > "badrec.file"
}
}
}' RS="#END\n" ORS="#END\n" FS="\n" file
[jaypal:~/Temp] cat badrec.file
#START Descriptor # Bad Record
#FIELD LOCATION="http://path.to/file/here&Value=FOO&OtherValue=BLAH"
#FIELD AnythingElse
#FIELD MyField="BAR"
#END
Les sections sont-elles séparées par les nouvelles lignes ou sont-elles l'une après l'autre?
Votre "bonne section" veut-elle avoir une double devis entre "Emplacement =" et "http:"?
Alors qu'est-ce qui fait précisément la mauvaise section?
valeur = foo code> dans l'URL vs.
bar code> dans le
myfield code>? (et est-il censé être une citation avant le
http code> dans la bonne section?)
Kevin - Le "mauvais" est exactement ça, j'ai une bonne valeur connue dans Myfield, et si cette valeur ne s'est pas présentée dans la chaîne de localisation, quelque chose s'est mal passé.