IPB

Bienvenue invité ( Connexion | Inscription )

 
Reply to this topicStart new topic
> Filtrer un fichier avec SED, et ne garder qu'un seul enregistrement
Options
Pixel44
posté 31 May 2015, 20:54
Message #1


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 3 307
Inscrit : 17 Jul 2004
Lieu : Nantes
Membre no 21 109



Bonjour,

Je débute avec SED et j'essaye de comprendre comment je peux garder uniquement un seul enregistrement.

Soit la commande :
Code
sed -n 's,.*<integer>\(.*\)</integer>,\1,p' /Users/Ronan/documents.txt | awk '{print "fichier : " $0}' | tail -3
dont je garde seulement les 3 derniers enregistrements :

fichier : 1
fichier : 2
fichier : 45

or je ne souhaite conserver pour la suite du traitement que le 1er (soit : fichier : 1).

J'ai bien compris la commande SED '2,3d' mon_fichier.txt qui supprime les lignes 2 à 3 mais je n'arrive pas à mettre en pratique en même temps que la ligne de filtrage.


--------------------
Go to the top of the page
 
+Quote Post
Guest_JacqR_*
posté 31 May 2015, 22:09
Message #2





Guests






Bonsoir,

Vous pouvez ajouter q à la commande, cela quittera sed après la première ligne.
Code
sed -n 's,.*<integer>\(.*\)</integer>,fichier : \1,p;q' /Users/Ronan/documents.txt
Mais, cela ne donnera rien, si ce que vous cherchez n'est pas dans la première ligne du fichier texte.


Edition :
Code
sed -n '/<\/integer>/{s,.*<integer>\(.*\)<\/integer>,fichier : \1,p;q;}' /Users/Ronan/documents.txt
ou
sed -n '1,/<\/integer>/s,.*<integer>\(.*\)</integer>,fichier : \1,p' /Users/Ronan/documents.txt

Cela quittera sed lorsqu'il trouvera le premier motif </integer>.

Ce message a été modifié par JacqR - 1 Jun 2015, 02:12.
Go to the top of the page
 
+Quote Post
Pixel44
posté 1 Jun 2015, 03:56
Message #3


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 3 307
Inscrit : 17 Jul 2004
Lieu : Nantes
Membre no 21 109



merci pour vos efforts mais cela ne fonctionne pas car la ligne que je chercher à récupérer se trouve parmi les 10 enregistrements retournés par la commande SED. La commande tail -5 l'affiche en 1er mais ce n'est pas réellement le 1er enregistrement.


--------------------
Go to the top of the page
 
+Quote Post
Guest_JacqR_*
posté 1 Jun 2015, 04:09
Message #4





Guests






Citation (Pixel44 @ 31 May 2015, 22:56) *
merci pour vos efforts mais cela ne fonctionne pas car la ligne que je chercher à récupérer se trouve parmi les 10 enregistrements retournés par la commande SED. La commande tail -5 l'affiche en 1er mais ce n'est pas réellement le 1er enregistrement.

J'ai ajouté deux autres commandes dans mon message (4 heures plus tard), en cas que le texte recherché ne se trouve pas dans la première ligne du fichier texte.

Sinon utilise la commande
Code
| head -n1
pour obtenir la première ligne de la sortie de ta commande

Ce message a été modifié par JacqR - 1 Jun 2015, 04:15.
Go to the top of the page
 
+Quote Post
Jaypee
posté 1 Jun 2015, 06:05
Message #5


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



La commande awk est plus spécialisée pour ça, et elle utilise une expression régulière comme sed.

Soit macb.txt contenant
aaabc
abbca
cabac

On imprime la ligne avec 2 b:
awk '/bb/ {print $0}' macb.txt
abbca

J-P
Go to the top of the page
 
+Quote Post
Pixel44
posté 1 Jun 2015, 16:59
Message #6


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 3 307
Inscrit : 17 Jul 2004
Lieu : Nantes
Membre no 21 109



merci

J'ai besoin de conserver un seul enregistrement dont je ne connais que le numéro d'ordre (le 1er) quelque soit son contenu. Je ne peux pas filtre sur le contenu car il ne contient qu'un chiffre qui peut varier.


--------------------
Go to the top of the page
 
+Quote Post
Guest_JacqR_*
posté 1 Jun 2015, 19:01
Message #7





Guests






Citation (Pixel44 @ 1 Jun 2015, 11:59) *
J'ai besoin de conserver un seul enregistrement dont je ne connais que le numéro d'ordre (le 1er) quelque soit son contenu. Je ne peux pas filtre sur le contenu car il ne contient qu'un chiffre qui peut varier.

Peux-tu nous donner un exemple de texte dans le fichier (quelques lignes), et le résultat que tu voudrais obtenir ?


Quels sont les résultats des autres commandes données dans ce fil ?
Go to the top of the page
 
+Quote Post
Jaypee
posté 1 Jun 2015, 19:04
Message #8


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



C'est possible:

awk ' NR == 1 {print $0}' macb.txt
aaabc

Mais pourquoi sed ou awk alors que head déjà cité par JacqR le fait parfaitement ?

head -1 mac.txt
aaabc

ou dans un script:
ligne=`head -1 macb.txt`
echo $ligne
aaabc

Attention ce ne sont pas des apostrophes mais des accents graves, penchés vers la gauche...

La blague d'informaticien se vérifie une fois encore:
J'ai un problème, je vais utiliser une expression régulière pour le résoudre... maintenant ça fait deux problèmes.

JP

Ce message a été modifié par Jaypee - 1 Jun 2015, 19:16.
Go to the top of the page
 
+Quote Post
Pixel44
posté 2 Jun 2015, 05:42
Message #9


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 3 307
Inscrit : 17 Jul 2004
Lieu : Nantes
Membre no 21 109



Citation (JacqR @ 1 Jun 2015, 20:01) *
Citation (Pixel44 @ 1 Jun 2015, 11:59) *
J'ai besoin de conserver un seul enregistrement dont je ne connais que le numéro d'ordre (le 1er) quelque soit son contenu. Je ne peux pas filtre sur le contenu car il ne contient qu'un chiffre qui peut varier.

Peux-tu nous donner un exemple de texte dans le fichier (quelques lignes), et le résultat que tu voudrais obtenir ?


Quels sont les résultats des autres commandes données dans ce fil ?


Vous avez raison, ce sera plus parlant

le fichier contient beaucoup de lignes que la commande SED filtre et qui renvoie précisément 12 enregistrements contenant au hasard un de ses chiffres soit : 0, >0 dont une valeur fixe 64
j'ai trouvé que l'enregistrement dont je cherche à récupérer le contenu est toujours le 8ème.

J'ai pensé que la commande TAIL -5 pourrait filtrer mais pas assez : je vois les 5 derniers (en partant de la fin du fichier)
J'ai essayé HEAD-8, mais la aussi il y a trop d'enregistrements : les 8 premiers enregistrements
J'ai essayé sur vos conseils AWK mais le filtre est sur la valeur or elle varie et je ne la connais pas au moment de la recherche.

C'est compliqué...

Ce message a été modifié par Pixel44 - 2 Jun 2015, 07:19.


--------------------
Go to the top of the page
 
+Quote Post
Jaypee
posté 2 Jun 2015, 06:09
Message #10


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



awk fonctionne aussi avec un script, au lieu de tout mettre sur la ligne de commande:

- Soit un fichier texte, filtres.awk contenant :
NR == 1 {print NR, "Ligne 1"}
/bb/ {print NR, "Ligne avec bb"}

- La commande devient:
awk -f filtres.awk macb.txt
1 Ligne 1
2 Ligne avec bb

Pour l'analyse ligne par ligne, awk est le bon outil, on peut travailler sur des fenêtres pour trouver la ligne après celle qui contient /bb/

JP

Ce message a été modifié par Jaypee - 2 Jun 2015, 06:10.
Go to the top of the page
 
+Quote Post
Pixel44
posté 2 Jun 2015, 07:35
Message #11


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 3 307
Inscrit : 17 Jul 2004
Lieu : Nantes
Membre no 21 109



Merci, vous m'avez beaucoup aidé et ça marche (je crois) :

Code
sed -n 's,.*<integer>\(.*\)</integer>,\1,p' /Users/Ronan/documents.txt | awk 'NR==8 { print "fichier : "$0 }'


--------------------
Go to the top of the page
 
+Quote Post
Guest_JacqR_*
posté 2 Jun 2015, 13:42
Message #12





Guests






Bonjour,


Citation (Pixel44 @ 2 Jun 2015, 02:35) *
Merci, vous m'avez beaucoup aidé et ça marche (je crois) :

Code
sed -n 's,.*<integer>\(.*\)</integer>,\1,p' /Users/Ronan/documents.txt | awk 'NR==8 { print "fichier : "$0 }'
Content que tu as trouvé.


Aussi, c'est possible de le faire en utilisant seulement la commande awk
Code
awk -F'<[/]?integer>' '/<integer>/ && ++n == 8 {print "fichier : "$2; exit}' /Users/Ronan/documents.txt


Info sur la commande :
-F'<[/]?integer>' : -F est le séparateur de champ dans la ligne, donc les séparateurs seront <integer> et </integer>
Si la ligne est "...xyz<integer>57</integer>bla..." : $2 contient 57, $1 contient "...xyz"
Si la ligne est "<integer>57</integer>bla..." : $2 contient 57, $1 est vide

/<integer>/ && ++n == 8 : si on trouve <integer> dans la ligne, on ajoute 1 à la variable n (n=0 au début)
si la variable n = 8 , on print le deuxième champ dans cette ligne (le nombre dans la balise <integer>) et on quitte awk
Go to the top of the page
 
+Quote Post
Guest_JacqR_*
posté 2 Jun 2015, 14:44
Message #13





Guests






Bonjour,

Si c'est pour cette question :
Voici un exemple pour obtenir le nombre de message non lu dans la boite "Indésirables" d'un compte :
Code
sed -n '/<string>Junk<\/string>/,/<\/integer>/s,.*<integer>\(.*\)<.*,non lu : \1,p' fichier.plist


/<string>Junk<\/string>/,/<\/integer>/ : on recherche une ligne qui contient >Junk< jusqu'à la prochaine ligne qui contient </integer>
Le résultat sera le nombre pour seulement la BAL "Indésirables".
Si c'est pour la INBOX, remplace Junk par INBOX
Go to the top of the page
 
+Quote Post
Pixel44
posté 3 Jun 2015, 05:50
Message #14


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 3 307
Inscrit : 17 Jul 2004
Lieu : Nantes
Membre no 21 109



Merci aussi

Citation (JacqR @ 2 Jun 2015, 15:44) *
Bonjour,

Si c'est pour cette question :
Voici un exemple pour obtenir le nombre de message non lu dans la boite "Indésirables" d'un compte :
Code
sed -n '/<string>Junk<\/string>/,/<\/integer>/s,.*<integer>\(.*\)<.*,non lu : \1,p' fichier.plist


/<string>Junk<\/string>/,/<\/integer>/ : on recherche une ligne qui contient >Junk< jusqu'à la prochaine ligne qui contient </integer>
Le résultat sera le nombre pour seulement la BAL "Indésirables".
Si c'est pour la INBOX, remplace Junk par INBOX


Je cherche à comprendre une subtilité :

- Le fichier .plist contient deux fois </integer> après <key>JUNK</key> or :

dans le 1er cas : /<string>Junk<\/string>/,/<\/integer>/[/b] : retourne bien la seconde valeur de </integer>
dans le 2nd cas : /<key>Junk<\/key>/,/<\/integer>/[/b] : retourne la première valeur de </integer> : Pourquoi s'arrête-t-il au premier </integer> ?


Rep : Je n'avais pas vu qu'il y avait aussi un autre Junk (<string>Junk</string>) juste après <key>Junk</key>, ça parait logique qu'il trouve le second </integer>... smile.gif

Ce message a été modifié par Pixel44 - 3 Jun 2015, 05:58.


--------------------
Go to the top of the page
 
+Quote Post
Jaypee
posté 3 Jun 2015, 06:29
Message #15


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Ne serait-il pas mieux d'envisager un langage de script plus sophistiqué?

OS X dispose en standard de Perl, Python et Ruby. Perl est sans doute le plus "vieille école".

Pour le dernier, Ruby, il y a cette bibliothèque qui permet d'extraire les valeurs des "key":
https://github.com/bleything/plist

L'exemple donné est:
result = Plist::parse_xml('path/to/example.plist')

result.class
=> Hash

"#{result['FirstName']} #{result['LastName']}"
=> "John Public"

result['ZipPostal']
=> "12345"

pour ce fichier:
CODE

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>FirstName</key>
<string>John</string>

<key>LastName</key>
<string>Public</string>

<key>StreetAddr1</key>
<string>123 Anywhere St.</string>

<key>StateProv</key>
<string>CA</string>

<key>City</key>
<string>Some Town</string>

<key>CountryName</key>
<string>United States</string>

<key>AreaCode</key>
<string>555</string>

<key>LocalPhoneNumber</key>
<string>5551212</string>

<key>ZipPostal</key>
<string>12345</string>
</dict>
</plist>


Dans un Terminal:
sudo gem install plist (pour installer la lib ruby)
irb (c'est la console ruby)

Code
[jaypee:~/Projects/MacBidouille]$ sudo gem install plist            
Password:
Successfully installed plist-3.1.0
Parsing documentation for plist-3.1.0
1 gem installed
[jaypee:~/Projects/MacBidouille]$ irb                            
irb(main):001:0> require 'plist'
=> true
irb(main):002:0> result = Plist::parse_xml('/Users/jaypee/Projects/MacBidouille/doc.plist')
=> {"FirstName"=>"John", "LastName"=>"Public", "StreetAddr1"=>"123 Anywhere St.", "StateProv"=>"CA", "City"=>"Some Town", "CountryName"=>"United States", "AreaCode"=>"555", "LocalPhoneNumber"=>"5551212", "ZipPostal"=>"12345"}
irb(main):003:0> result['ZipPostal']
=> "12345"


J-P

Ce message a été modifié par Jaypee - 3 Jun 2015, 19:43.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 25th April 2024 - 05:34