web-dev-qa-db-fra.com

Faire que les variables montrent une colonne avec awk

J'ai cette variable:

collumn=2

Je veux le faire changer avec la 2ième colonne de la ligne qui commence par john à partir d'un fichier, avec awk.

Par exemple, dans ce fichier sample.txt:

bill|copper|real|bruce
john|gold|fake|jhin
johny|silver|geniue|madrit

Cela ne marche pas:

collumn=2
awk -F '|' /^jonh/ -v collumn="$2" sample.txt
echo "$collumn"

Je veux qu'il imprime gold.

En gros, je veux changer la valeur d'une variable avec awk.

3
cater pilar

Vous utilisez deux langues: Bash et AWK.

Bash ( qui est ​​votre shell ) et AWK sont tous les deux langages de programmation , et ils vous permettent tous les deux de stocker des données dans variables . Mais les variables de votre shell et les variables de AWK sont complètement séparées. En outre, les variables dans AWK n'existent plus à la fin de votre script AWK. Autrement dit, une fois que votre commande awk est terminée, vos variables AWK sont parties.

Vous pouvez passer un texte de la forme _var=val_ en tant que argument de ligne de commande à la commande awk. Ceci affecte une variable dans AWK . Cela n'affecte en aucune façon les variables du shell. Lorsque vous utilisez l'option _-v_ (par exemple, _-v var=val_), elle indique à la commande awk d'assigner la variable avant d'exécuter votre script AWK, mais il s'agit toujours d'une variable AWK, et non d'une variable Shell.

Votre objectif est d’attribuer du texte provenant d’une colonne spécifique d’une ligne correspondante à une variable Shell . Vous pouvez le faire. Mais commençons par résoudre un problème plus simple. Cette commande trouve les lignes commençant par john et affiche le contenu de la deuxième colonne de chacune de ces lignes. Si vous avez juste une ligne qui commence de cette façon, il affiche un élément. Si vous n'avez pas de telles lignes, rien ne s'affiche, et si vous avez plusieurs lignes qui commencent par john, plusieurs éléments seront affichés sur des lignes distinctes:

_awk -F '|' '/^john/ { print $2 }' sample.txt
_

Le script AWK dans cette commande est _/^john/ {print $2}_. Je l'ai inclus entre guillemets simples (_'_ _'_) afin qu'il soit traité comme une chaîne unique et non modifié par le shell , avant d’être passé à la commande awk. Sinon, le shell interpréterait le script AWK comme cinq mots et opérateurs séparés pour le shell lui-même ( et non AWK), ce qui le conduirait à ne prendre que _/^john/_ comme script AWK. Tout ce qui suit sera traité comme un nom de fichier à transmettre à awk, ce qui ne fonctionnera pas. Le shell aurait aussi développer $2 , et exécuterait Fractionnement du mot ​​et extension du nom de fichier (globbing) sur le résultat (bien que le fait d'insérer _$2_ dans guillemets doubles comme dans votre question empêcherait le fractionnement et la suppression). Vous ne voulez pas que de telles choses se produisent. En règle générale, il est judicieux de mettre vos scripts AWK entre guillemets afin qu'ils soient fidèlement transmis à la commande awk.

Avec le fichier _sample.txt_ présenté dans votre question, cette commande produit cette sortie:

_gold
silver
_

Il imprime le texte à partir de deux lignes correspondantes, plutôt que d'un seul. Puisque vous voulez juste gold, vous ne voulez probablement pas vraiment faire correspondre toutes les lignes qui commencent avec john. Au lieu de cela, vous souhaiterez probablement faire correspondre uniquement les lignes où l’entrée de la première colonne est john exactement . (L’un des avantages de résoudre une version simple d’un problème est d’abord de vous aider à affiner votre connaissance du problème que vous souhaitez résoudre.) Vous ne pouvez sélectionner que les lignes dont la première entrée de colonne est exactement john comme ceci:

_awk -F '|' '$1 == "john" { print $2 }' sample.txt
_

Cela affiche:

_gold
_

Maintenant, résolvons le problème dans son intégralité. L'affectation de variables Shell n'est pas quelque chose que vous pouvez faire dans un script AWK. Non seulement cela ne fait pas partie du langage AWK, mais la commande awkdevrait être implémentée en tant que partie de votre shell pour que cela soit possible. Cela ne signifie pas que vous ne pouvez pas faire ce que vous voulez faire - vous pouvez absolument le faire. Cela signifie simplement qu'au lieu d'essayer d'écrire du code AWK à affecter à une variable du shell, vous devez utiliser le shell lui-même pour le faire.

Vous avez une commande awk qui affiche la valeur que vous souhaitez attribuer à une variable. Ainsi, vous pouvez utiliser substitution de commande dans le shell pour vous aider à effectuer l'affectation. Cette commande l'assigne à une variable Shell appelée entry (mais vous pouvez utiliser le nom de votre choix à la place de entry, tel que column):

_entry="$(awk -F '|' '$1 == "john" { print $2 }' sample.txt)"
_

Cela fonctionne parce que le shell remplace _$(_ _)_ et tout ce qu'il contient avec la sortie produite en exécutant la commande qu'il contient. C'est substitution de commande . Notez que lorsque vous affectez une variable Shell comme celle-ci, vous devez et non avoir des espaces autour du signe _=_.

(En passant, vous remarquerez peut-être que le texte john est colorisé ci-dessus comme s'il n'était pas réellement cité. Il s'agit en fait d'un bogue dans le logiciel qui fournit la coloration syntaxique sur ce site Web, ce qui est dû au fait qu'il n'analyse pas complètement le contenu de le _"_ _"_ extérieur, de sorte qu'il ne sache pas que le _"_ _"_ est à l'intérieur de _$(_ _)_. Ce n'est pas un problème lorsque vous exécutez la commande, cependant.)

Vous pouvez vérifier que gold a été affecté à la variable Shell entry en exécutant:

_echo "$entry"
_

Cela affichera:

_gold
_

Pour plus d'informations sur les variables dans le langage AWK, voir cette section 6.1.3 Variables dans Gawk: Effective AWK Programming , qui est la documentation officielle de GNU awk (gawk). Bien qu'il documente GNU awk, il explique ce qui est spécifique à GNU awk et ce qui peut également être utilisé dans d'autres implémentations du langage AWK. La commande awk de votre système Ubuntu soit mawk ou gawk , en fonction du logiciel que vous avez installé et de la façon dont vous l'avez configuré. Une façon de voir lequel doit exécuter _awk -W version_.

2
Eliah Kagan