J'ai un fichier hotfix_final
qui ressemble à ceci:
usage_type=$( cat /opt/abc/ps/usage.txt ) current_date=$( date +%x ) lines=$( wc -l /home/abc/hotfix_final | awk '{print $1}' ) count=0 while $count <= $lines; do hf_link=$( awk if( NR=$count ) '{print $1}' hotfix_final ) relase_date=$( awk if( NR=$count ) '{print $2}' hotfix_final ) count=$(( count+1 )) done < hotfix_final
J'ai besoin d'écrire un script shell qui lit le fichier ligne par ligne puis prend la date qui est à côté du lien dans une variable afin que je puisse le comparer à la date actuelle. Si les dates sont égales et usage_type = 4
, j'ai besoin du script pour obtenir le lien.
Ce que j'ai essayé jusqu'à présent:
https://download.abc.com 06/24/2019 https://download.abc.com 06/26/2019 https://download.abc.com 07/05/2019
$ lines
pour afficher le nombre maximum de lignes à lire.
$ hf_link
pour obtenir le lien
$ release_date
pour obtenir la date à côté de $ hf_link
Maintenant, je ne sais pas comment écrire la partie qui vérifie si $ usage_type == 4
et $ current_date = $ relase_date
sont vrais, et si oui, wget le lien. Cela doit être fait individuellement pour chaque ligne du fichier.
3 Réponses :
Peut être fait avec quelques corrections de votre script:
Vous devez prendre soin de citer vos variables pour éviter que les valeurs ne soient fractionnées sur un espace ou sur des caractères répertoriés dans la variable $ IFS
.
date +% x
renverrait une date avec un format différent sur un système avec des paramètres régionaux différents dans la variable d'environnement $ LC_TIME
.
Le format % x
serait MM / JJ / AA
lors du réglage de LC_TIME = en_US
, mais il y a une petite chance (bien que très peu probable) que les paramètres régionaux en_US
peuvent ne pas être disponibles pour le système.
Il est alors préférable d'utiliser un format explicite indépendant des paramètres régionaux de +% d /% m /% Y
, pour être sûr du format de date.
Voici une version fixe:
#!/usr/bin/env bash # Early exit this script if the usage.txt file does not contain the value 4 grep -Fqx 4 /opt/abc/ps/usage.txt || exit # Store current date in the MM/DD/YYYY format current_date="$(date +%d/%m/%Y)" # Iterate each line from hotfix_final # and read the variables hf_link and release_date while read -r hf_link release_date; do if [ "$current_date" = "$release_date" ]; then wget "$hf_link" fi done </home/abc/hotfix_final # Set the file as input for the whole while loop
mais comment le shell sait-il que pour chaque ligne du fichier hotfix_final
$ hf_link
représente les liens tandis que $ release_date
représente les dates à côté des liens?
La commande read
lit une ligne à la fois. Ensuite, lorsqu'il est présenté avec plusieurs variables à lire, il utilise des espaces ou les caractères définis dans la variable d'environnement $ IFS
pour délimiter les champs dans la ligne et affecter des valeurs aux variables dans le même ordre que les arguments des variables lues.
Vous voulez quitter tôt si usage_type
n'est pas 4, au lieu de le comparer encore et encore à l'intérieur de la boucle.
Vous l'avez seulement déplacé, il est toujours comparé à chaque itération.
Désolé pour la faute de frappe fgrep -f
dans ma réponse, vous voulez corriger cela ici aussi.
Voici une refactorisation de la réponse acceptée pour éviter la boucle fugace while read -r
.
#!/bin/sh grep -Fqx 4 /opt/abc/ps/usage.txt || exit awk -v current_date="$(date +%d/%m/%Y)" ' $2 == current_date { print $1 }' /home/abc/hotfix_final | xargs -r -n 1 wget
L'option -r
pour xargs
est une extension GNU; si vous ne l'avez pas, ce n'est pas critique, mais cela permet d'éviter un message d'erreur lorsque le script Awk ne produit aucune sortie.
Dans votre prochain projet, vous voulez vous assurer d'utiliser un moins insensé format de date dans des fichiers lisibles par ordinateur.
Je suppose que vous pouvez le faire dans un script awk autonome avec son propre #! / Usr / bin / env awk
shebang
J'ai aussi commencé avec la gestion de usage.txt
dans le script Awk, mais cela avait moins de sens pour quelqu'un qui n'est probablement pas très familier avec Awk, donc je voulais le garder très simple et structuré.
Cela pourrait fonctionner pour vous (GNU Parallel):
[ $(<usageFile) -eq 4 ] && parallel -a fixFile -C' +' [ {2} = $(date +%m/%d/%Y) ] \&\& wget {1}
Utilisez test
pour interroger le fichier d'utilisation et s'il est défini sur 4
utilisez le parallèle pour terminer la tâche. Parallel utilise le fichier fix
et l'option -C
avec l'expression rationnelle d'un ou plusieurs espaces pour nommer les colonnes du fichier {1}
comme l'url et {2}
comme date. Le test est utilisé à nouveau pour vérifier la colonne de date par rapport à la date d'aujourd'hui et une correspondance wget
l'URL.
Il y a beaucoup de nombreuses erreurs dans ce script. (1) : citez correctement votre awk:
awk '{if (NR == $ count) print $ 1}'
(2) instructions if devrait faire des comparaisons et non des affectations:if (NR == $ count)
(3) les variables shell doivent être passées à awk correctement:awk -v count = $ count '{if (NR == count) print $ 1}'
(4) n'analysez pas un fichier en bash avec une boucle while comme vous le faites :, utilisez simplement un while correct en combinaison avec read, vous pouvez sauter le awk pour extraire les variables. Voir la réponse de Léa GrisVoir stackoverflow.com/a/38627863/874188 pour savoir pourquoi la lecture des numéros de ligne est très souvent un anti-modèle.