Question grignoter une sous-chaîne d'un résultat grep


Étant donné un fichier journal, je vais généralement faire quelque chose comme ceci:

grep 'marker-1234' filter_log

Quelle est la différence en utilisant '' ou "" ou rien dans le motif?

La commande grep ci-dessus produira plusieurs milliers de lignes; ce que je désire Dans ces lignes, il y a généralement une partie des données que je recherche. Parfois, j'utilise awk pour imprimer les champs que je recherche. Dans ce cas, le format du journal change, je ne peux pas compter uniquement sur la position, pour ne pas mentionner que les données enregistrées peuvent pousser la position vers l'avant.

Pour que cela soit compréhensible, disons que la ligne de journal contenait une adresse IP, et c’était tout ce que je recherchais, donc je pourrai plus tard la trier et la rendre unique et obtenir des comptes de comptage.

Un exemple peut être:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: foo@bar.example.com to bar@foo.example.com [stat-xyz9876]

La première commande grep me donnera plusieurs milliers de lignes comme ci-dessus, à partir de là, je veux le diriger vers quelque chose, probablement sed, qui peut extraire un motif et imprimer uniquement le motif.

Pour cet exemple, utiliser une adresse IP suffirait. J'ai essayé. Est sed incapable de comprendre [0-9] {1,3}. comme motif? Je devais [0-9] [0-9] [0-9]. ce qui a donné des résultats étranges jusqu'à ce que le modèle entier créé.

Ce n'est pas spécifique à une adresse IP, le modèle changera, mais je peux l'utiliser comme modèle d'apprentissage.

Merci à tous.


4
2018-04-09 01:18


origine


Cela semble très lié à la programmation, même des commandes simples comme bash grep et awk sont à mon avis mieux répondu sur stackoverflow. - Josh K
@Josh: SU a beaucoup de guerriers de ligne de commande Linux qui peuvent gérer ce genre de questions, et il est le bienvenu ici. c'est peut-être une de ces questions qui conviendrait à l'un ou l'autre des sites, donc cela dépend vraiment du demandeur. - quack quixote
J'ai réfléchi et pour être honnête, je ne savais pas où le poster. Je suis allé avec le nom des sites, en pensant que SO est plus général, et SU est plus de type administrateur. Je trouve que la plupart des scripts shell rapides sont liés à l’administration. Bien sûr, vous vous lancez dans de grands projets exclusifs tcl ou bash pour une raison ou une autre, auquel cas je les limiterais à la programmation et à la publication SO. C'était plus un paquebot et SU semblait être une bonne maison. Désolé si j'ai posté au mauvais endroit, mais cela semble être une zone grise dans certains cas. - user17245
@allentown: en fait, Server Fault est plus un problème de type admin; Super User est plus un truc d'utilisateur final. (mais les utilisateurs finaux utilisateurs de pouvoir), de toute façon, cette question est probablement bienvenue sur tout SO / SF / SU. vous avez déjà accepté une réponse, donc si vous êtes satisfait, vous pouvez l'appeler fait. ou si vous souhaitez que nous puissions le migrer vers SO / SF; marquez-le simplement pour attirer l'attention du modérateur et dites-nous où l'envoyer. Merci! - quack quixote
@quack: C'est bien, je pensais juste qu'une meilleure réponse pourrait être trouvée là-bas, mais il semble que ce soit déjà trouvé. - Josh K


Réponses:


Je ne sais pas sur quel OS vous êtes, mais sur FreeBSD 7.0+ grep a un -o option pour renvoyer uniquement la partie correspondant au motif. Donc tu pourrais
grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

Retourne une liste des adresses IP du "filter_log" ...

Cela fonctionne sur mon système, mais encore une fois, je ne sais pas ce que votre version de grep prend en charge.


7
2018-04-09 02:28



Je pense que toutes les réponses sont d'excellentes façons d'apprendre et d'aborder le résultat final avec la même réponse. J'aime particulièrement celui-ci car il est facilement mémorisable et ne fait que chaîner plusieurs commandes grep. Sur Mac OS X, je semble avoir l'option -o et, bien sûr, utiliser l'option -E assez souvent. Merci pour votre réponse - user17245


vous pouvez faire tout cela en un seul awk commander. Pas besoin d'utiliser d'autres outils

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)

3
2018-04-09 02:44



Merci, ça marche bien, awk peut parfois vous faire mal à la tête, mais je m'habitue à FOO .... un aspect de pochette rapide dans la coque. Très puissant. - user17245


Vous pouvez raccourcir le second grep un peu comme ça:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

Pour répondre à votre première question, les guillemets doubles permettent au shell d'effectuer diverses opérations, comme l'expansion des variables, mais empêchent certains méta-caractères de devoir être échappés. Les guillemets simples empêchent le shell d'effectuer ces extensions. L'utilisation de guillemets laisse les choses ouvertes.

$ empty=""
$ text1="some words"
$ grep $empty some_file
(It seems to hang, but it's just waiting for input since it thinks "some_file" is 
the pattern and no filename was entered, so it thinks input is supposed to come
from standard input. Press Ctrl-d to end it.)
$ grep "$empty" some_file
(The whole file is shown since a null pattern matches everything.)
$ grep $text1 some_file
grep: words: No such file or directory
some_file:something
some_file:some words
(It sees the contents of the variable as two words, the first is seen as the 
pattern, the second as one file and the filename as a second file.)
$ grep "$text1" some_file
some_file:some words
(Expected results.)
$ grep '$text1' some_file
(No results. The variable isn't expanded and the file doesn't contain a
string that consists of literally those characters (a dollar sign followed
by "text1"))

Vous pouvez en apprendre plus dans la section "QUOTING" de man bash


2
2018-04-09 04:16



Super écrit, merci. J'ai besoin de mieux maîtriser cela avec le regad sur IFS aussi, j'étais assez accroché à ça l'autre jour, mais j'ai réussi à faire en sorte que l'IFS joue bien. C’est une chose terrible quand on a réglé et oublié l’IFS, on peut se demander si WTF continue pendant une heure. - user17245
C'est une bonne idée de prendre l'habitude de toujours garder la valeur de IFS et le restaurer dès que possible: saveIFS="$IFS"; IFS=","; do_something; IFS="$saveIFS"; do_other_stuff - Dennis Williamson
+1 Bon appel sur le regex, je ne l'utilise pas beaucoup, donc j'ai tendance à être un peu inefficace. - Chris S


Rechercher le xargs commander. Vous devriez pouvoir faire quelque chose comme:

grep 'marker-1234' filter_log | xargs grep "(" | cut -c1-15

Cela peut ne pas être exactement, mais xargs est la commande que vous voulez utiliser


1
2018-04-09 01:38