1
votes

expression awk qui fonctionne sur awk v4.0.2 mais pas sur> = 4.2.1

J'ai cette commande awk:

host com

ce qu'elle fait est d'obtenir le domaine à partir du nom d'hôte:

host.com

cette commande fonctionne sur CentOS 7 (awk v 4.0.2), mais il ne fonctionne pas sur ubuntu 19.04 (awk 4.2.1) ni alpine (gawk 5.0.1), le résultat est:

echo www.host.com |awk -F. '{$1="";OFS="." ; print $0}' | sed 's/^.//'


3 commentaires

Essayez de définir OFS avant de définir $ 1 sur vide.


vous pouvez couper à la place. echo www.host.com | couper -d '.' -f2,3


Ou, echo www.host.com | grep -o '\ w \ w * [.] \ w \ w * $' (désolé, pas dirigé vers vous @DigvijayS) ou avec une expression régulière étendue grep -Eo '\ w + [.] \ w + $ '


4 Réponses :


5
votes

Pour les exemples que vous avez fournis, veuillez essayer de suivre. Cela essaiera de faire correspondre l'expression régulière du tout premier . au dernier de la ligne, puis imprimera après le premier point jusqu'au dernier de la ligne.

echo www.host.com | awk 'BEGIN{FS=OFS="."} {$1="";sub(/\./,"");print}'


Correction du code d'OP:

Dans le cas où OP voudrait utiliser son propre code essayé, suivre peut être utile. Il y a 2 points ici: 1er- Nous n'avons pas besoin d'utiliser une autre commande avec awk pour le traitement. 2ème- Nous devons définir les valeurs de FS et OFS dans la section BEGIN que vous faites dans everyline.

echo www.host.com | awk 'match($0,/\..*/){print substr($0,RSTART+1,RLENGTH-1)}'


0 commentaires

4
votes

Pour obtenir le domaine, utilisez:

$ echo and.with.peculiar.fqdns.like.co.uk | 
awk '
BEGIN {
    FS=OFS="."
    pecs["co\034uk"]
}
{
    print (($(NF-1),$NF) in pecs?$(NF-2) OFS:"")$(NF-1),$NF
}'
like.co.uk

Expliqué:

$ echo if.you.have.arbitrarily.long.fqdns.example.com |
awk 'BEGIN{FS=OFS="."}{print $(NF-1),$NF}'
example.com

Cela fonctionne également si vous avez des fqdns arbitrairement longs: p>

awk '
BEGIN {                 # before processing the data
    FS=OFS="."          # set input and output delimiters to .
}
{
    print $(NF-1),$NF   # then print the next-to-last and last fields
}'

Et oui, drôle, votre version fonctionne vraiment avec la 4.0.2. Et awk version 20121220.

Mise à jour:

Mise à jour avec quelques fonctionnalités de vérification de contenu, voir les commentaires. Existe-t-il des domaines qui dépassent trois niveaux?:

$ echo www.host.com | awk 'BEGIN{FS=OFS="."}{print $(NF-1),$NF}'
host.com


4 commentaires

Imaginez un domaine comme: www.foo.co.uk


co.uk ? Est-ce que cela n'est même plus brexiste? :RÉ


Merci, mais cela fonctionne mais si le domaine est composé de plus de deux parties, il imprimera toujours les deux dernières, par exemple www.host.com.co renverrait com.co au lieu de host.com.co. La réponse suivante extrait correctement le domaine sur cet exemple.


@Juancho Cela devrait apparaître dans la question d'origine avec des exemples et la sortie attendue associée. Plus de chance la prochaine fois.



3
votes

Vous avez obtenu 2 très bonnes réponses sur awk mais je pense que cela devrait être géré avec cut en raison de la simplicité qu'il offre pour obtenir tous les champs à partir d'une position connue:

host.com

echo 'www.host.com' | cut -d. -f2-

Les options utilisées sont:

  • -d. : définir le délimiteur comme .
  • -f2- : Extraire tous les champs à partir de la position 2


1 commentaires

Je ne connaissais pas l'opérateur "-" avec coupe, en effet cela pourrait être plus simple. Merci.



2
votes

Ce que vous observez était un bogue dans GNU awk qui a été corrigé dans la version 4.2.1. Le changlog déclare:

12/08/2014 Arnold D. Robbins

OFS en cours de configuration devrait reconstruire $ 0 en utilisant l'ancien OFS si $ 0 doit être reconstruit. Merci à Mike Brennan pour l'avoir signalé.

  • awk.h ( rebuild_record ): déclarer.
  • eval.c ( set_OFS ): S'il n'est pas appelé depuis var_init () , vérifiez si $ 0 a besoin d'être reconstruit. Si tel est le cas, analysez complètement l'enregistrement et reconstruisez-le. Faites pointer OFS vers une copie séparée du nouvel OFS pour la prochaine fois, car OFS_node-> var_value-> stptr était déjà mis à jour à ce stade.

  • field.c ( rebuild_record ): Est maintenant externe au lieu de statique. Utilisez OFS et OFSlen au lieu de la valeur de OFS_node.

Lors de la lecture du code dans l'OP, il indique:

var=www.foo.com
echo ${var#*.}

qui, selon POSIX fait ce qui suit:

  1. -F. : définit le séparateur de champ FS pour représenter le -character
  2. lire un enregistrement
  3. Effectuer le fractionnement des champs avec FS="."
  4. $ 1 = "" : redéfinissez le champ 1 et reconstruisez l'enregistrement $ 0 en utilisant OFS . À ce stade, OFS est défini comme un espace unique. Si l'enregistrement $ 0 était www.foo.com , il lit maintenant _foo_com (les traits de soulignement représentent des espaces). Recalculez le nombre de champs qui sont désormais un seul car il n'y a plus de FS disponible.
  5. OFS = "." : redéfinissez le séparateur de champ de sortie OFS pour être le -character. C'est là que le bogue se produit. Le awk Gnu savait qu'une reconstruction devait avoir lieu, mais l'a déjà fait avec le nouvel OFS et non avec l'ancien OFS .
  6. ** print $ 0 ': ** imprime l'enregistrement $ 0 qui est maintenant _foo_com`.

Le changement minimal de votre programme serait:

awk 'BEGIN{FS=OFS="."}{$1="";print $0}'

Le changement propre serait:

awk -F. '{OFS="."; $1=""; print $0}'

Le changement parfait serait de remplacer le awk et le sed par le cut solution d'Anubahuva

Si vous avez une variable avec ce nom là-dedans, vous pouvez utiliser:

awk -F. '{$1="";OFS="." ; print $0}'

p>


0 commentaires