2012-07-24 1 views
0

J'utilise linux et bash. J'ai un fichier texte avec le contexte généré en cours d'exécution par un autre programme. La longueur, le nombre de lignes et le contenu du fichier texte ont changé de temps en temps. Mais il y a un certain modèle inchangé dans le texte, un exemple typique estcherchant un moyen d'extraire un motif à partir d'un fichier texte dans Linux

123098230984LD # 2e3 123098230984LD # 23234 XER_3424324_23424 33: 34: 35: noeud: 9-72-1408 $ 1231313 * 3435322 lien vers le port: 323 3424242424LD # 2234 332424LD # 23424234

ici, je veux extraire le modèle "noeud: NUMERO dE NUMÉRO NUMÉRO" et "port: NUMBER" mais où il se produit dans le texte varie de de temps en temps aussi. Maintenant, je extrait manuellement l'information. Je me demande s'il existe un moyen d'extraire l'information automatiquement. Ce qui rend vraiment difficile le contenu change à chaque fois que le fichier est généré.

Répondre

0

Vous pouvez utiliser sed pour extraire les champs désirés en se débarrassant des bits indésirables:

pax> echo 'junk node:9-72-1408 more junk port:323 last junk' 
    | sed -E 's/^.*(node:[0-9]+-[0-9]*-[0-9]*).*(port:[0-9]+).*$/\1 \2/' 
node:9-72-1408 port:323 

Les .* bits représentent simplement une ordure et les parenthèses sont utilisées pour « capturer » le texte correspondant afin qu'il puisse être utilisé dans le remplacement (comme \1 et \2).


Barre latérale:

Si votre version de sed ne supporte pas -E pour regexes prolongée, il peut soutenir -r, comme certaines versions de GNU sed.

Sinon, vous devrez échapper aux parenthèses et + caractères:

pax> echo 'junk node:9-72-1408 more junk port:323 last junk' 
    | sed 's/^.*\(node:[0-9]\+-[0-9]\+-[0-9]\+\).*\(port:[0-9]\+\).*$/\1 \2/' 
node:9-72-1408 port:323 

Le code source pour GNU sed contient ce petit extrait:

/* Undocumented, for compatibility with BSD sed. */ 
    case 'E': 
    case 'r': 

mais cela semble avoir été introduit en 4.2 (c'est-à-dire en 4.2 mais pas en 4.1.5, la dernière de la série 4.1). Voir here pour plus de détails.


Et, si vous avez besoin des valeurs réelles des variables, vous pouvez utiliser quelque chose comme:

pax> inpstr='junk-here node:9-72-1408 more-junk port:323 last-junk' 

pax> node=$(echo "$inpstr" | sed -E 's/^.*node:([0-9]+-[0-9]+-[0-9]+).*$/\1/') 

pax> port=$(echo "$inpstr" | sed -E 's/^.*port:([0-9]+).*$/\1/') 

pax> echo $inpstr 
junk-here node:9-72-1408 more-junk port:323 last-junk 

pax> echo $node 
9-72-1408 

pax> echo $port 
323 

(en tenant compte des commentaires précédents sur l'utilisation -r ou en ajoutant supplémentaire échapper pour « moins » sed implémentations).

+0

merci. J'ai essayé la commande mais elle ne semble pas fonctionner dans mon système. Je ne sais pas pourquoi, il n'y a pas d'option -E dans sed et la version pour sed dans mon système est GNU sed version 4.1.5. J'essaye man sed, il n'y a que -e ou -expression, j'ai essayé ça aussi, mais ça ne me donne pas le résultat attendu. Il montre "sed: -e expression # 1, char 57: référence invalide \ 2 sur RHS de la commande" s "" – user1285419

+1

@ user1285419, essayez d'utiliser '-r' pour les expressions rationnelles étendues plutôt que le' -E'. '-E' fonctionne sur GNUsed4.2.1 même si ce n'est pas dans la page de manuel. Sinon, vous devrez modifier légèrement les expressions rationnelles.Je vais mettre à jour la réponse. – paxdiablo

+0

@ user1285419: plus loin, le commutateur '-E' a été ajouté à la version 4.2, ce qui explique pourquoi votre 4.1.x ne l'a pas. Cependant, depuis 4.1.0 a '-r', vous pouvez simplement utiliser cela à la place. – paxdiablo

Questions connexes