2010-11-11 17 views
3

Je souhaite obtenir quelques lignes d'un fichier qui se trouve dans un fichier .gz compressé. Le fichier .gz contient de nombreux fichiers txt et je veux rechercher une chaîne dans tous ces fichiers txt et j'ai besoin d'obtenir la ligne précédente 3 en sortie, y compris la ligne en cours (où la chaîne de recherche est présente).Script Unix à rechercher dans un fichier .gz compressé

J'ai essayé zgrep et j'ai obtenu le numéro de ligne, mais quand j'utilise head ou tail commande Cela donne quelques valeurs de déchets. Je pense que nous ne pouvons pas utiliser les commandes head ou tail avec des fichiers compressés contenant plusieurs fichiers.

S'il vous plaît suggérer s'il ya une manière simple?

+0

Est-il possible de retitrer ceci pour qu'il soit clair qu'il s'agit d'un .tar.gz. Voulez-vous les trois lignes précédentes dans un seul fichier, ou est-ce correct si cela signale une ligne d'un fichier précédent? – wnoise

+0

trois lignes précédentes à partir d'un fichier/même fichier – CFUser

+0

Fichiers Zip! = Tar-balls. Veuillez corriger le libellé. –

Répondre

5

L'essentiel de la façon d'accomplir cela est d'obtenir les noms des fichiers dans l'archive à rechercher, et d'extraire leur contenu à rechercher, sans rien extraire d'autre. Parce que nous ne voulons pas écrire dans le système de fichiers, nous pouvons utiliser l'indicateur -O pour extraire à la sortie standard.

tar -tzf file.tar.gz | grep '\.txt' | xargs tar -Oxzf file.tar.gz | grep -B 3 "string-or-regex" concaténera tous les fichiers dans le fichier .tar.gz avec des noms se terminant par ".txt", et grep eux pour la chaîne donnée, en émettant également les 3 lignes précédentes. Il ne vous dira pas quel fichier provient de l'archive, et les "trois lignes précédentes" peuvent en fait provenir du fichier précédent.

Vous pouvez faire à la place:

for file in $(tar -tzf file.tar.gz | grep '\.txt'); do 
    tar -Oxzf file.tar.gz "$file" | grep -B 3 --label="$file" -H "string-or-regex" 
done 

qui respectent les limites des fichiers et rapporter les noms de fichiers, mais être beaucoup moins efficace.

(-z dit tar il est gzip compressé. -t répertorie le contenu. -x extraits. -O réoriente la sortie standard plutôt que le système de fichiers. Anciens tar s ne peuvent pas avoir le drapeau -O ou -z et veulent les drapeaux sans -: par exemple tar tz file.tar.gz)

Bon, vous avez donc un grep inutilisable. Nous pouvons résoudre cela avec awk!

#!/usr/bin/awk -f 
BEGIN { context=3; } 
{ add_buffer($0) } 
/pattern/ { print_buffer() } 
function add_buffer(line) 
{ 
    buffer[NR % context]=line 
} 
function print_buffer() 
{ 
    for(i = max(1, NR-context+1); i <= NR; i++) { 
     print buffer[i % context] 
    } 
} 
function max(a,b) 
{ 
    if (a > b) { return a } else { return b } 
} 

Ce ne sera pas s'unir matchs adjacents, contrairement grep -B, et peut ainsi répéter les lignes qui sont dans les 3 lignes de deux matches différents.

+0

mon OS ne supporte pas les commandes -B ou -A – CFUser

+0

Est-ce qu'il supporte -C? Est-ce un problème d'obtenir 3 lignes après? – wnoise

+0

malheureusement pas de C aussi :( – CFUser

0

Est-ce que c'est peut-être un gzip d'un fichier tar? Le plus simple est simplement d'extraire le tout et d'utiliser les outils habituels sur les fichiers extraits.

+2

oui son gzip d'un fichier tar. Je ne peux pas extraire, bcoz il contient des fichiers énormes et aura des problèmes d'espace disque – CFUser