1
votes

Linux / Shell découpant un gros fichier texte

Given

File1

$ grep -i 'uniquename1' | (not sure how to slice the line with regex "*:*:*") | grep $thisline file2

File2

$ command uniquename2
apple
$ command uniquename1
hello
$ command uniquename3
hello

Je souhaite créer une méthode qui fait essentiellement ceci

uniquekey1:hello
uniquekey2:apple
uniquekey3:hello

Ainsi, étant donné un nom unique de fichier1, il utilisera sa clé de fichier2 pour obtenir le lien vers lequel il est lié. S'il ne trouve pas de nom unique, ne faites rien.

MA TENTATIVE

uniquename1:somethinguseless:somethinguseless:uniquekey1
uniquename2:somethinguseless:somethinguseless:uniquekey2
uniquename3:somethinguseless:somethinguseless:uniquekey3


0 commentaires

4 Réponses :


1
votes

sed rend cela relativement facile. Par exemple:

$ awk -F: -v name=uniquename2 '
    FILENAME == "file1" { $1 == name && key = $NF } 
    FILENAME == "file2" { if ($1 == key) print $NF }
' file1 file2
apple

ou

sed '/match/s/find/replace/`

Vous utilisez simplement la substitution de commande $ (sed -n '/uniquename3/s/.*[:ITED//p' f1) pour obtenir la uniquekey de uniquename en coupant la partie de début de la ligne , puis faites la même chose pour le résultat pour obtenir la chaîne souhaitée avec sed -n "/$(command)/s/.*[:[/lp" en utilisant des guillemets doubles sur le externe pour permettre à la substitution de commande de se développer.

La forme de la commande de base sed utilisée est la substitution normale s / find / replace avec une correspondance de motif de tête pour un total

$ sed -n "/$(sed -n '/uniquename3/s/.*[:]//p' f1)/s/.*[:]//p" f2
hello

Le -n supprime l'impression normale de l'espace du motif et le p à la fin, le fait imprimer lorsque la correspondance et la substitution réussissent.

Si uniquename ou uniquekey Contient des caractères d'expression régulière

Compte tenu de votre commentaire sur votre fichier réel renvoyant une erreur, il apparaît que chaque est unique nom ou uniquekey dans vos fichiers réels contiennent des caractères qui peuvent être interprétés comme des expressions régulières. Dans ce cas, une solution GNU awk utilisant la variable FILENAME pour extraire les informations nécessaires de chaque fichier en fonction des champs séparés par ':' devrait fonctionner, par exemple

$ sed -n "/$(sed -n '/uniquename2/s/.*[:]//p' file1)/s/.*[:]//p" file2
apple

Faites-moi savoir si vous avez des problèmes là-bas. De plus, si vous pouvez publier des exemples réels (disons 10 lignes chacun) de vos file1 et file2 , cela vous aiderait.


6 commentaires

Quand je l'essaye avec un fichier plus gros, j'obtiens ceci: "sed: -e expression # 1, char 15: commande inconnue:` m '"


Avez-vous une ligne DOS se terminant par l'un des fichiers? (il n'y a pas de 'm' dans la commande)


@aki Aussi, que peut être quelque chose d'inutile: quelque chose d'inutile ? S'il y a des caractères significatifs en tant que regex , alors je peux voir que cela pose des problèmes.


peu importe, ils peuvent être n'importe quoi. Existe-t-il alors un moyen d'obtenir la queue d'une ligne: /?


Ok, donnez-moi une seconde pour réfléchir à la façon de supprimer toute signification particulière. Je ne suis pas sûr, si tel est le cas, que tout ce qui interprète une expression régulière fonctionnera.


De plus, la clé unique n'a pas de «:» comme symbole. La clé unique ne contient que des chiffres et des caractères alphabétiques



0
votes

L'utilitaire cut a été conçu pour ce type de données:

#!/bin/bash
KEY=$(grep -i -e "^$1:" file1.txt | cut -d ':' -f 4)
grep -e "^$KEY" file2.txt | cut -d ':' -f 2


4 commentaires

cela fonctionne presque, mais un problème était que si le début du nom unique était similaire, il le saisirait. par exemple: "aaabc123: ...." et "abc123". Si je voulais saisir abc123, il saisirait aaabc123 à la place


J'ai modifié la première commande grep pour qu'elle corresponde du début de la ligne au premier deux-points. J'ai modifié le deuxième grep pour supposer un deux-points à la fin de la clé et faire correspondre du début de la ligne à la fin de la clé.


Il m'est récemment apparu que le: quelque chose d'inutile: quelque chose d'inutile: peut contenir «:», ce qui me donne la mauvaise sortie pour certains d'entre eux. Cela fonctionne cependant pour la plupart de tous ne pas avoir «:». uniquename / uniquekey ne contient pas ':' cependant.


Sans une meilleure description de vos données, nous ne faisons que deviner la solution.



1
votes

Voici un script awk qui scanne les deux fichiers une seule fois. Contrairement à la solution imbriquée grep effectuant des analyses de fichiers uniqueId * (uniqueId - 1) .

script.awk

 awk -v keyArg="uniquename2" -f script.awk file1 file2 

Exécution:

BEGIN {FS=":"} # field separator is :
FNR == NR && $1 == keyArg {id = $NF} # find the id in first file
FNR == NR {next} # continue scanning first file
$1 == id {print $2} # find the id in second file and print its 2nd field value


1 commentaires

FNR == NR && $ 1 == keyArg {id = $ NF; next} doit être FNR == NR {if ($ 1 == keyArg) id = $ NF; next} donc le next s'applique à toutes les lignes de file1, pas seulement à la ligne 1 où $ 1 correspond à keyArg.



1
votes

La bonne réponse est la suivante:

$ awk -v tgt='uniquename2' -F':' 'NR==FNR{map[$1]=$2; next} $1==tgt{print map[$NF]}' file2 file1
apple

ou presque (voir mon commentaire ci-dessous) ce que @DudiBoy a publié .


0 commentaires