web-dev-qa-db-fra.com

Comment imprimer des colonnes avec awk et éditer simultanément une seule colonne?

Toujours au niveau débutant!

Exemple d'une ligne dans mon file.txt:

158.45.456.756 - - [04/Feb/2016:10:51:24 -0500] "GET /tiles/1.0.0/cd/base/1/85/785.png?wb75678545=75D2503E HTTP/1.1" 200 8848 "http://site/map.html" "Mozilla/5.0 (Windows NT 6.1; MOM64; Trident/7.0; mv:10.0) like Blah"

Résultat Je veux accomplir:

[04/Feb/2016:10:51:24-0500]/tiles/1.0.0/cd/base/1/85/7852008848

Ce que j'ai essayé jusqu'à présent

awk '{ print $4 $5 $7 $9 $10}' retournera:

[04/Feb/2016:10:51:24-0500]/tiles/1.0.0/cd/base/1/85/785.png?wb75678545=75D2503E2008848

ce qui n'est pas bon parce que cette partie .png?wb75678545=75D2503E ne devrait pas être contenue dans la ligne.

J'ai aussi essayé d'imprimer simplement la 7ème colonne et de tout supprimer après le dernier point avec awk '{ print $7}' | grep -Po '.*(?=\.)' qui m'a renvoyé le résultat que je souhaite pour une colonne spécifique:

/tiles/1.0.0/cd/base/1/85/785

cependant, je finis par être laissé de côté avec une autre partie de la ligne.


Question

Comment puis-je imprimer toutes les colonnes dont j'ai besoin et en même temps ou avant de ne modifier que la 7ème colonne?

1
vayacondios2015

Avec awk:

awk '{print $4 $5 gensub("(.*/[^.]+)\\..*", "\\1", 1, $7) $9 $10}' 
  • print imprime les champs requis sans aucune modification, seule la partie requise du 7e champ étant extraite avec gensub()

  • Dans gensub("(.*/[^.]+)\\..*", "\\1", 1, $7), le motif Regex "(.*/[^.]+)\\..*" correspond à la partie précédant le . après le dernier /, et le place dans le groupe capturé 1, puis le reste. comme correspond par \\..*. Dans le remplacement, seul le groupe capturé est utilisé pour obtenir cette partie uniquement

  • Dans le motif Regex (.*/[^.]+)\\..*, la partie du groupe capturé () c'est-à-dire que dans .*/[^.]+, .*/ correspond de manière avide au dernier /, puis [^.]+ correspond à la partie jusqu'à la prochaine ., elle est conservée en tant que groupe capturé car c'est la partie souhaitée, et nous utiliserons le groupe de remplacement, puis \\. correspond à un littéral ., alors .* correspond au reste de la chaîne

Pour commenter, si vous voulez garder . dans le match, c’est-à-dire vouloir . aussi:

awk '{print $4 $5 gensub("(.*/[^.]+\\.).*", "\\1", 1, $7) $9 $10}' 

Exemple:

% awk '{print $4 $5 gensub("(.*/[^.]+)\\..*", "\\1", 1, $7) $9 $10}' <<<'158.45.456.756 - - [04/Feb/2016:10:51:24 -0500] "GET /tiles/1.0.0/cd/base/1/85/785.png?wb75678545=75D2503E HTTP/1.1" 200 8848 "http://site/map.html" "Mozilla/5.0 (Windows NT 6.1; MOM64; Trident/7.0; mv:10.0) like Blah"'
[04/Feb/2016:10:51:24-0500]/tiles/1.0.0/cd/base/1/85/7852008848

% awk '{print $4 $5 gensub("(.*/[^.]+\\.).*", "\\1", 1, $7) $9 $10}' <<<'158.45.456.756 - - [04/Feb/2016:10:51:24 -0500] "GET /tiles/1.0.0/cd/base/1/85/785.png?wb75678545=75D2503E HTTP/1.1" 200 8848 "http://site/map.html" "Mozilla/5.0 (Windows NT 6.1; MOM64; Trident/7.0; mv:10.0) like Blah"'
[04/Feb/2016:10:51:24-0500]/tiles/1.0.0/cd/base/1/85/785.2008848
2
heemayl