IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

[bash] Problème sur un programme en bash


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de nekcorp
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2006
    Messages : 592
    Par défaut [bash] Problème sur un programme en bash
    Bonjour,

    Un collègue de bureau m'avait fait un code en bash qui me permet de supprimer ou commenter une ligne à l'aide d'un "$" dans un fichier A lorsque le nombre dans le fichier B est trouvé dans le fichier A.

    Pour être plus précis, j'ai un fichier dans lequel j'ai des nombres les uns en dessous des autres comme ceci (coorespond à mon fichier B):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    2115050
    2165410
    2125953
    2000000
    5200025
    1523215
     
    etc.......
    Le programme va lire chaque nombre et va les chercher dans mon fichier A qui se présente comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    FORCE       2500 2115050       0      1.-2448.27 2683.11 5590.67
    FORCE       2500 2115061       0      1.-2448.27 2683.11 5590.67
    FORCE       2500 2095050       0      1.-2448.27 2683.11 5590.67
    FORCE       2500 2095060       0      1.-2448.27 2683.11 5590.67
    $
    $				
    $
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    FORCE    2500    2165410 0      5394.09 -.003393.323574 -.946197
    FORCE    2500    2165420 0      2686.05 -.003393.323574 -.946197
    FORCE    2500    2165430 0      5509.89 -.003393.323574 -.946197
    FORCE    2500    2175410 0      5395.21 -.003393.323574 -.946197
    FORCE    2500    2175420 0      2687.27 -.003393.323574 -.946197
    FORCE    2500    2175430 0      5509.98 -.003393.323574 -.946197
    $
    FORCE    2600    270800  0      612.051 -.003669.985618 -.16895
    FORCE    2600    270801  0      689.983 -.003804.98932  -.145711
    FORCE    2600    270804  0      689.596 -.003805.989918 -.141593
    FORCE    2600    270830  0      79.359  -.005185.999987 4.7803-5
    FORCE    2600    270831  0      158.767 -.005185.999987 1.3383-4
    FORCE    2600    270832  0      158.769 -.005154.999987 1.7677-4
    FORCE    2600    270930  0      2868.73  0.     .490462 -.871463
    FORCE    2600    270940  0      4572.04  0.     .469962 -.882687
    FORCE    2600    270950  0      7981.49  0.     .383634 -.923485
    FORCE    2600    280010  0      6617.53 -.007605 0.     .999971
    FORCE    2600    280020  0      9923.29 -.007618-.052568.998588
    FORCE    2600    280030  0      13226.3 -.007669-.104955.994447
    FORCE    2600    280040  0      13226.4 -.007769-.174333.984656
    FORCE    2600    280050  0      13225.8 -.007911-.242862.970029
    FORCE    2600    280060  0      13225.5 -.008097-.310206.950635
    FORCE    2600    280070  0      13225.4 -.008332-.376028.926571
    FORCE    2600    280080  0      13224.6 -.008619-.43998 .897966
    FORCE    2600    280090  0      13224.  -.008947-.501783.864947
    FORCE    2600    280100  0      13581.7 -.009323-.562686.826618
    FORCE    2600    280110  0      13572.5 -.009735-.61915 .785213
    FORCE    2600    280120  0      13205.3 -.010175-.673957.738701
    Les nombres cherché se trouve dans le troisième champ

    Voici le code qui permet de faire cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     
    #!/bin/ksh
    #
    #
    #--------------------------------------------------------------------------------
    # INPUTS
    #--------------------------------------------------------------------------------
    dat_files=""
     
    # Get inputs
    ls -al
    echo "-- INPUTS --"
    echo " This script removes nodes force/moment in dat files"
    echo "Give DAT files:"
    read dat_files
    echo "Give nodes IDs list to remove:"
    read target_node_ids
    target_node_ids=`cat $target_node_ids`
    # Check inputs valididy
    TMP_VAR=""
    for file in $dat_files
    do
    	if [ -f $file ] ; then
    		TMP_VAR="$TMP_VAR $file"
    	else
    	  echo ""
    	  echo " File $file doesn't exist."
    	fi
    done
    dat_files=$TMP_VAR
     
    if [ "$dat_files" = "" ] ; then
    	echo "No DAT input files !"
    	exit
    fi
     
    # Ask for confirmation
    echo ""
    echo "Selected DAT files:"
    for file in $dat_files
    do
    	echo $file
    done
    echo "Selected nodes IDs to remove: $target_node_ids"
    echo ""
    echo "Proceed (y)?"
    read answer
    if [ "$answer" != "y" ] ;then
    	exit
    fi
    #
    #--------------------------------------------------------------------------------
    # PROCESS
    #--------------------------------------------------------------------------------
    #
    for curr_dat_file in $dat_files
    do
    	echo ""
    	echo "File "$curr_dat_file
    	# Copy DAT File
    	cp $curr_dat_file $curr_dat_file"_old"
    	# Process each target node
    	target_node_count=0
    	# FORCE/MOMENT cards need to be in small format!
    	pos_index=9
    	((pos_index_end=$pos_index+8))
    	grep "^FORCE " $curr_dat_file | cut -c$pos_index-$pos_index_end | sed "s/[ ]//g" > tmp_col.tmp
    	for curr_target_node in $target_node_ids
    	do
                    target_node_count=$(($target_node_count+1))
    		k=`grep $curr_target_node tmp_col.tmp | wc -l`
    		if [ $k -ge 1 ] ; then
    			i=1
    			while  [ $i -le $k ]
    			do
    				raw_to_delete=`grep "^FORCE[0-9 ].*$curr_target_node" $curr_dat_file | head -n $i`
    ###########
    # 1=removal
    #				sed "/^$raw_to_delete$/d" $curr_dat_file > tmp
    ###########
    # 2=comment
    				sed "s/$raw_to_delete/\$$raw_to_delete/g" $curr_dat_file > tmp
    ###########
    				mv tmp $curr_dat_file
    				echo " Following card has been commented = <"$raw_to_delete">"
    				i=$(($i+1))
    			done
    		fi
            done
    	echo $target_node_count" nodes removed"
    done
    rm -f tmp_col.tmp
    #
    echo ""
    echo "Job done!"
    #--------------------------------------------------------------------------------
    # END OF FILE
    #--------------------------------------------------------------------------------
    Mon soucis est le suivant, lorsqu'un nombre du fichier B existe plus de deux fois dans mon fichier A le fichier de sortie est vide.

    Je ne suis pas expert je comprend plus ou moins le code mais là je suis bloqué.

    quelqu'un pour m'aider m'aiguiller ?

    Ps : Je n'ai plus contact avec ce collègue sinon je me serai adressé à lui directement

    Merci d'avance

  2. #2
    Membre expérimenté Avatar de fransoo
    Inscrit en
    Novembre 2009
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 209
    Par défaut
    J'essayerais quelque chose avec grep, du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -f "fichier B" "fichier A"
    qui sortira toutes les lignes ayant l'occurence extraite du fichier B.
    C'est le contraire qu'on veut ! on va donc envoyer la sortie pour la comparer avec le fichier A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -f "fichier B" "fichier A" | diff -y --suppress-common-lines "fichier A" -
    Attention, le tiret à la fin signale qu'on utilise STDIN comme fichier N°2.
    On obtient, je pense, quelque chose de très proche du résultat escompté, en une seule ligne de commande. Toute la puissance de *nix
    P.S.
    Selon l'usage final, d'autres outils comme awk, join ou sed pourraient être encore plus efficaces.

  3. #3
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par fransoo Voir le message
    J'essayerais quelque chose avec grep, du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -f "fichier B" "fichier A"
    qui sortira toutes les lignes ayant l'occurence extraite du fichier B.
    C'est le contraire qu'on veut !
    Donc quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -fv "fichier B" "fichier A"
    Sauf que tu oublies une contrainte ici, c'est la 3eme colonne...
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  4. #4
    Membre expérimenté Avatar de fransoo
    Inscrit en
    Novembre 2009
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 209
    Par défaut
    Citation Envoyé par gangsoleil Voir le message
    Donc quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -fv "fichier B" "fichier A"
    Sauf que tu oublies une contrainte ici, c'est la 3eme colonne...
    Si la chaîne est susceptible d'apparaître dans une autre colonne, il faudra alors utiliser awk, sinon, ce n'est pas nécessaire.
    J'ai essayé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -fv "fichier B" "fichier A"
    mais comme grep lit le fichier B ligne à ligne la non-occurence des chaînes arrivera toujouirs à être juste, c'est donc tout le fichier qui sort. C'est ce que j'en ait déduit quand j'ai essayé.

  5. #5
    Membre éclairé Avatar de nekcorp
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2006
    Messages : 592
    Par défaut
    En fait la partie du code à regarder est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    #--------------------------------------------------------------------------------
    # PROCESS
    #--------------------------------------------------------------------------------
    #
    for curr_dat_file in $dat_files
    do
    	echo ""
    	echo "File "$curr_dat_file
    	# Copy DAT File
    	cp $curr_dat_file $curr_dat_file"_old"
    	# Process each target node
    	target_node_count=0
    	# FORCE/MOMENT cards need to be in small format!
    	pos_index=9
    	((pos_index_end=$pos_index+8))
    	grep "^FORCE " $curr_dat_file | cut -c$pos_index-$pos_index_end | sed "s/[ ]//g" > tmp_col.tmp
    	for curr_target_node in $target_node_ids
    	do
                    target_node_count=$(($target_node_count+1))
    		k=`grep $curr_target_node tmp_col.tmp | wc -l`
    		if [ $k -ge 1 ] ; then
    			i=1
    			while  [ $i -le $k ]
    			do
    				raw_to_delete=`grep "^FORCE[0-9 ].*$curr_target_node" $curr_dat_file | head -n $i`
    ###########
    # 1=removal
    #				sed "/^$raw_to_delete$/d" $curr_dat_file > tmp
    ###########
    # 2=comment
    				sed "s/$raw_to_delete/\$$raw_to_delete/g" $curr_dat_file > tmp
    ###########
    				mv tmp $curr_dat_file
    				echo " Following card has been commented = <"$raw_to_delete">"
    				i=$(($i+1))
    			done
    		fi
            done
    	echo $target_node_count" nodes removed"
    done
    rm -f tmp_col.tmp
    #
    echo ""
    echo "Job done!"
    #--------------------------------------------------------------------------------
    # END OF FILE
    #--------------------------------------------------------------------------------
    Mon soucis est le suivant : Imaginons qu'a un moment je tombe sur le nombre 9999999 présent dans mon fichier B.

    La routine va chercher dans mon fichier A dans le troisième champ le si le nombre correspondant est le même .... Si c'est le cas il supprime ou commente la ligne en question à l'aide de ces lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ###########
    # 1=removal
    #				sed "/^$raw_to_delete$/d" $curr_dat_file > tmp
    ###########
    # 2=comment
    				sed "s/$raw_to_delete/\$$raw_to_delete/g" $curr_dat_file > tmp
    ###########
    Cependant pour être sur que le nombre n'est pas présent plusieurs fois j'imagine que le programme continu de regarder chaque champ jusqu'a la fin du fichier. Lorsque le nombre est présent une seconde fois le programme fonctionne correctement et supprime ou commente cette seconde ligne en question. Le problème intervient lorsque le nombre est présent une troisième fois ..... A ce moment le programme continu de tourner mais le fichier de sortie est nul (vide). A mon avis il y a un soucis sur une boucle ... Mais je ne sais pas trop laquelle.

    J'espère avoir été plus précis.

    Encore merci de votre aide

  6. #6
    Membre expérimenté Avatar de fransoo
    Inscrit en
    Novembre 2009
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 209
    Par défaut
    Je dirais que le problème doit se situer au niveau de sed (qui parcourt tout le fichier A). À essayer : enlever le g de global dans sed
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "s/$raw_to_delete/\$$raw_to_delete/g"
    pour avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "s/$raw_to_delete/\$$raw_to_delete/"
    car je pense qu'il n'y a qu'une occurence par ligne et sed parcourt TOUTES les lignes de toute façon.

Discussions similaires

  1. Petit problème sur petit programme
    Par tamerla dans le forum Débuter avec Java
    Réponses: 7
    Dernier message: 19/01/2014, 11h32
  2. Problème sur un programme
    Par Hunshy dans le forum Débuter
    Réponses: 5
    Dernier message: 19/09/2012, 21h33
  3. Débutant en Ruby - Problème sur un programme
    Par Mo0oN dans le forum Ruby
    Réponses: 17
    Dernier message: 16/12/2008, 12h33
  4. Réponses: 3
    Dernier message: 26/11/2008, 15h52
  5. redirigé la sortie d'un script bash sur un programme C
    Par onaipadesmickey dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 07/08/2007, 18h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo