Découpage de ligne en bash

Tags: #<Tag:0x00007f63e5f732f8> #<Tag:0x00007f63e5f73230>

Bonjour,

j’ai un fichier texte qui contient des lignes dont je voudrais extraire les données séparément.

Chaque ligne est de la forme suivante:

<espaces1>New File<espaces>[nombre]<espaces>[nomfichier]

espaces1 contient 0 à N espaces
espaces contient 1 à N espaces
[nombre] est de la forme classique uniquement avec des chiffres comme 114554 mais aussi de la forme 2.1 m ou 3.5 g
[nomfichier] contient un nom de fichier dans lequel n’importe quel caractère peut apparaitre, caractère speciaux, caractères accentués de n’importe quelle langue, des espaces, des signes de ponctuation en plus du point de l’extension

Je veux pouvoir extraire [nombre] et le nom du fichier

A vérifier mais avec AWK cela donnerai ça :

awk '{print $2 " " $3}' ton_fichier_texte.txt

Le séparateur par défaut étant l’espace il prendra comme motif des colonnes, tu choisi celles (les colonnes) de ton choix et tu peux ajouter un espace comme séparateur à ta sortie.

Il y a aussi un espace dans la chaîne New File, donc plutôt awk '{print $3 " "$4}'

Voire même awk '{print $(NF-1) " "$NF}', comme ça awk ne sort que l’avant-dernier et le dernier champ, ça peut être moins casse-tête.

Par contre, si [nomfichier] contient des espaces (Zargos dit que ça peut être une possibilité), ça ne fonctionne plus.

1 J'aime

Bien vu, j’ai généré un fichier rapidement et zappé cet espace …

Je propose de brûler cette hérésie d’espaces dans les noms de fichier … on n’est pas sous Windows là :joy:

Quoi qu’il arrive que ce soit avec sed ou awk si il y a des espaces partout il faudra impérativement manipuler le fichier avant un traitement afin de réduire la complexité au strict minimum.

1 J'aime

awk permet justement de ne rien avoir à manipuler.
Il s’agit juste d’extraire les 2 dernières colonnes, le nombre d’espaces étant indifférent, à supposer que nomfichier soit bien sans espace ou correctement quoté: « nom fichier »

$ echo '     New File  7     nomfichier' | awk '{print $(NF-1),$NF}'
 7 nomfichier

Justement non, considère que nomfichier contient tous les caractères potyentiels du code ascii en anglais, français, finlandais, suedois, norvegien, allemand, espagnol, norvégien :slight_smile:

et en plus le champ nombre peut etre de la forme « 2.1 m » donc avec un espace aussi

Il s’agit d’un log de robocopy sous windows server :slight_smile:

1 J'aime

On ne peut pas modifier le nopm du fichier non plus :slight_smile:

Aucune importance. Non considéré comme des « espaces » par awk.
Maintenant, aucune commande ne pourra deviner ce que tu ne peux pas spécifier toi même, sans contre exemples concrets pour tester.

1 J'aime

J’ai à priori trouvé une regexp qui fait le taf avec https://regex101.com/:

/^\s*New\sFile\s*([0-9]*\.*[0-9]{1}\s{0,1}[mg]{0,1}[^\s])\s+(.*)/gm

Je peux lister avec $1;$2\n mais je ne sais pas comment utiliser ensuite :slight_smile:

1 J'aime

IL y a aussi des espaces dans les noms

Un exemple simple:

           New File               98628        Request #8066375 New user ANGELIKA MAJZNER requested by Marek Hofman.pdf
            New File              101281        RE_ ITRP #4262824.pdf
            New File              104305        RE_ ITRP #4273049.pdf
            New File              117862        RE_ Request #8066375 New user ANGELIKA MAJZNER requested by Marek Hofman.pdf
            New File              186578        FW_ Request #10512656_ New user ALEKSANDRA WOJCIK requested by Marek Hofman.pdf
            New File               1.0 m        FW_Request #14562002 Change user Betul DONER requested by Betul DONER.pdf
            New File               1.1 m        RE_Request #14752052 URGENT Add roles.pdf
            New File               52598        Approval Task #10580730.pdf
            New File               70891        FW_ BW1 for Michael Braem =_ NOT REQUIRED #5181407.pdf
            New File               92967        RE_ ITRP #5008197.pdf
            New File              137736        RE_ ITRP #5015580.pdf
            New File               79180        RE_ Task #5181407_ Michael Braem_ Authorization Office Approval.pdf
            New File               74666        R_ ITRP #5008144.pdf
            New File               92952        FW_ Approval Task #12068586_ SAP Authorization Key-User Approval for Christel Bentein.pdf
            New File              133542        FW_ ITRP request for new employee Jill Lindner  #4971723).pdf
            New File              118159        FW_ ITRP request for new employee Jill Lindner  #4971723.pdf
            New File              106385        FW_ Request #8532717 REQUEST FOR EMANUELA VALLONE - REQUEST APPROVAL FROM MR.KOGISO & MR.OLDRATI.pdf
            New File               68404        ITRP #4898696 and #5016047.pdf
            New File               69486        ITRP #4901331.pdf
            New File              119831        RE_ ITRP #4985493 - SAP Authorization request for Suzi SUMERLEVI .pdf
            New File               82182        RE_ ITRP #4993766.pdf
            New File              136451        WG_ ITRP request for new employee Jill Lindner  #4971723.pdf
            New File               99287        FW_ Request #12309805 Change user Els Vandecasteele requested by Els Vandecasteele (11535274).pdf
            New File              122429        RE_ Request #12303593 Change user Lien Soete requested by Lien Soete.pdf
            New File              159232        2018.09.26 Request #8923600  Change from Jens Gouwy - Autofattura documents should be printed in SAP.msg
            New File              182272        2018.09.26 Request #8923750  Change from Jens Gouwy - New VAT rate percentage in the Netherlands.msg
            New File               76897        2021.03.09 No reference on CN from factories_Request #19190818 _ Daikin Europe NV.pdf
            New File              115712        2019.11.29 Table_ Request #12928311 FW_ Reconciliation Intrastat vs VAT - September.msg
            New File              149504        2019.12.03 Table Intrastat_ Request #12928311 FW_ Reconciliation Intrastat vs VAT - September.msg
            New File              164352        Request #35047363_ Change from Evelien De Meulemeester - Change VAT & invoicing information on purchase order.msg
            New File              118272        Request #35074066 I need help on my ITC client account - Client Name_ Daikin_ Legal Entity_ 1000 Daikin Europe _ Jurisdiction_ Denmark.msg
             New File              162304        2021.08.10 Altaf - FW_ Request #20981958_ Change from Altaf Husain - E-invoicing implementation.msg
            New File              540672        2021.12.10 Live 10 dec 2021_ Request #20981958 Change from Altaf Husain - E-invoicing implementation.msg
            New File              193024        2023.05.16 Altaf - meeting RE_ Tax No# 3009563733 Daikin_ E-Invoicing Phase 2 - Wave 3 announcement  _ ??????? ???????????(??????? ???????) - ????? ??????? 3.msg

Donc, si l’input est ‹ nimporte quoi ›, sans aucun délimiteur, l’output de n’importe quelle commande sera aussi ‹ n’importe quoi ›.
C’est pour ça que des exemples/contre exemples concrets sont impérativement nécessaires pour se faire une idée précise.

Voilà un exemple ‹ simple › !

echo '       New File              118272        Request #35074066 I need help on my ITC client account - Client Name_ Daikin_ Legal Entity_ 1000 Daikin Europe _ Jurisdiction_ Denmark.msg' | \
  sed 's/[^0-9]*//'

118272        Request #35074066 I need help on my ITC client account - Client Name_ Daikin_ Legal Entity_ 1000 Daikin Europe _ Jurisdiction_ Denmark.msg

Bonjour,
un exemple avec grep en utilisant une expression rationnelle Perl en definissant un groupe:

fab@fabien:~$ grep -oP 'New File[ ]*\K([0-9.]*[ ]*[mg]?)' <<< """
New File              104305        RE_ ITRP #4273049.pdf
New File                117862        RE_ Request #8066375 New user ANGELIKA MAJZNER requested by Marek Hofman.pdf
New File              1.3 g         FW_ Request #10512656_ New user ALEKSANDRA WOJCIK requested by Marek Hofman.pdf
""" 
104305        
117862        
1.3 g
fab@fabien:~$
1 J'aime

Si on veut aussi avoir les noms de fichiers :

grep -oP 'New File[ ]*\K([0-9.]*[ ]*[gm]?)[ ]*(.*)'

Malheureusement le nombre d’espace n’est pas constant :slight_smile:

en fait j’ai fini par trouver, le soucis c’est qu’il y a des caractères de contrôle et des caractères accentué finlandais, danois, norvegien, allemand, etc…

#!/bin/bash

fic=$1
fout=$2
lasdtdir=""
count=0
nnewfile=`grep -E '^i\s*New\sFile' $fic | wc -l`
nnewdir=`grep -E '^i\s*New\sDir' $fic | wc -l`
nerrfile=`grep -E 'ERROR 112 \(0x00000070\) Copying File' $fic | wc -l`
echo "*****************************************************************************"
echo "*                       Date : $( date )"
echo "*                    File in : $fic"
echo "*                   File out : $fic2"
echo "* Number of New Dir detected : $nnewdir"
echo "* Number of New File detected: $nnewfile"
echo "* Number of File with error  : $nerrfile"
echo "*****************************************************************************"

while read line
do
        nname=""
        size=""
        fileis=""
        pattern=""
#       echo "$count : line=$line"
        if [[ "$line" =~ EUOSMSFS011 ]]; then
                lastdir=`echo $line | grep -Eo '\/\/EUOSMSFS011.*'`
#               echo "lastdir=$lastdir"
        fi
        pattern="^i\s*New\sDir"
        if [[ "$line" =~ $pattern ]]; then
                echo "d;$count;$lastdir" > $fout
        fi
        pattern="^i\s*New\sFile"                                                                                                                                                                                  
        if [[ "$line" =~ $pattern ]]; then                                                                                                                                                                        
#               echo "$count: Nouveau fichier"                                                                                                                                                                    
                size=`echo $line | sed -r 's/^i\s*New\sFile\s*([0-9]*\.*[0-9]{1}\s{0,1}[mg]{0,1}[^\s])\s+(.*)/\1/'`
                nname=`echo $line | sed -r 's/^i\s*New\sFile\s*([0-9]*\.*[0-9]{1}\s{0,1}[mg]{0,1}[^\s])\s+(.*)/\2/'`
                fileis=`echo $lastdir$nname`
#               echo "$count : size=$size"
#               echo "$count : nname=$nname"
#               echo "$count : lastdir=$lastdir"
#               echo "$count : fileis=$fileis"
                echo "f;count;$fileis" > $fout
        fi
#       echo "$count : END : line=$line"
        ((count++))
        echo "Line count : $count"
done < $fic

Ça tombe bien, la solution sed proposée est totalement indépendante du nombre d’espaces…
As-tu vraiment essayé ? J’ai un sérieux doute.
Ou donne un contre exemple pour tester pour vérifier que ‹ ça marche pas ›.

Ton approche comporte quand même des limites et est bien dépendante du nombre d’espaces

fab@fabien:~$ echo "XXX123 AB c DD" | sed -r 's/[^0-9]*//'
123 AB c DD
fab@fabien:~$ echo "XXX123           AB c DD" | sed -r 's/[^0-9]*//'
123           AB c DD
fab@fabien:~$

Non conforme à la demande initiale puisqu’il manque au moins un espace.

$ echo "XXX 123           AB c DD" |sed 's/[^0-9]*//'
$ echo " XX  XY 123       AB c DD" |sed 's/[^0-9]*//'
123           AB c DD

@zargos
Pour dire les choses plus directement:
Essayer de faire un ‹ script › pour quelque-chose d’aussi simple, une fois qu’un exemple concret a été montré un peu tardivement, est surprenant.
L’important est le choix de l’outil, et sed est la tronçonneuse idéale.
grep sert à ‹ chercher › du texte, mais il n’y a rien à chercher ici; juste tronçonner avant le premier chiffre (la demande initiale).
Il n’y a même pas besoin de PERL puisqu’une solution POSIX suffit plus que largement.
Un peu l’impression que l’objectif est de ne surtout pas tester ce qui est proposé, mais de tout faire pour trouver quelque-chose de plus compliqué, pour une raison pas très claire.

La demande est:

et grep est un bon outil pour ça…

C’est très bien les expressions rationnelles Perl, elles sont utilisées dans beaucoup de langage dont Python…
Après chacun fait comme il lui plait et utilise les technos qui lui plaisent. Tant que ça fonctionne, tout va bien :wink:

1 J'aime