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
4 Réponses :
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.
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
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
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.
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
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.
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é .