Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications
Applications Questions sur l'utilisation d'applications, du shell, et des interfaces graphiques (KDE, Gnome, XFCE... )
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
Vieux 13/02/2010, 17h02   #1
Invité de passage
 
Sinuakin Jean
Inscription : février 2010
Messages : 8
Détails du profil
Informations personnelles :
Nom : Sinuakin Jean

Informations forums :
Inscription : février 2010
Messages : 8
Points : 1
Points : 1
Par défaut [Awk] y a-t-il équivalent à read ? (intéraction dynamique avec l'utilisateur)

Bonjour à tous,
je cherche un moyen d'obtenir dans un script awk, le même effet que ces commandes ont dans un script bash :

Code :
1
2
3
 
echo -n "$fr	"
read var
... ou qu'un scanf par exemple en C.

Ce que voudrais, c'est que le script "attende" que l'utilisateur entre quelque chose, puis le stocke dans une variable (pour ensuite le comparer avec une autre chaîne de caractères).

Merci d'avance.

PS: je suis débutant en shell, awk, ...
sinuakin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 10h05   #2
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
Bonjour,

la commande awk est assez peu utilisée de la sorte, mais c'est tout-à-fait possible. Par exemple s'il faut entrer une veleur unique pour un fichier:
Code :
awk 'BEGIN {printf "entrez var: "; getline var < "/dev/stdin"} {print var, $2}' file_in
Ou alors s'il faut entrer une valeur par ligne de fichier:
Code :
awk '{printf "entrez var pour %s: ", $1; getline var < "/dev/stdin"; print var, $2}' file_in
__________________
Un problème bien posé est déjà résolu (H. Bergson).
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 11h24   #3
Invité de passage
 
Sinuakin Jean
Inscription : février 2010
Messages : 8
Détails du profil
Informations personnelles :
Nom : Sinuakin Jean

Informations forums :
Inscription : février 2010
Messages : 8
Points : 1
Points : 1
Bonjour, oui c'est celle-là qu'il me faut : entrer une valeur par ligne de fichier.

Merci beaucoup, j'ai testé en ligne de commande et ça marche.

Mais est-il aussi possible de le mettre dans un script dont le shebang est #!/usr/bin/awk -f ? J'ai essayé sans succès, voilà le (début de) code :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/awk -f
# lancer le script: awk -f test.awk < input_file

BEGIN {
	print "\nEntrez les valeurs correspondantes :\n"
	FS = "\t*"
}

$1 == "" || $1 == " " { next } # pour ne pas traiter les lignes vides ou commençant par une tabulation ou un espace

{
	printf "%s: ", $1
	getline var < "/dev/stdin"
	# ... suite du code ...
}
...
Le script n'attend pas que l'utilisateur rentre quelque chose, il passe d'emblée à l'enregistrement suivant; donc il doit falloir écrire différemment le chemin "/dev/stdin" (dans le script; parce qu'en ligne de commande ça fonctionne) ?
sinuakin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 12h09   #4
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
Et avec le fichier test.awk comme ceci?
Code :
1
2
3
4
5
6
7
8
#!/bin/awk
 
! /^$|^[ \t]/ \
{
  printf "%s: ", $1
  getline var < "/dev/stdin"
  # ... suite du code ...
}
Pour lancer la commande:
Code :
awk -f test.awk input_file
__________________
Un problème bien posé est déjà résolu (H. Bergson).
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 13h59   #5
Invité de passage
 
Sinuakin Jean
Inscription : février 2010
Messages : 8
Détails du profil
Informations personnelles :
Nom : Sinuakin Jean

Informations forums :
Inscription : février 2010
Messages : 8
Points : 1
Points : 1
Ah excellent, merci beaucoup :>
L'erreur venait donc de l'option -f en trop.

Peut-être que ce code pourra servir à d'autres débutants; le voilà, avec un exemple d'utilisation :

script lt.awk :
Code :
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
 
#!/bin/awk
 
BEGIN {
	print "\nEntrez la traduction en finnois des expressions suivantes, ou : \n q pour quitter\n c pour afficher la correction\n"
 
	FS = " *\t+ *"
	nb_total = sc = 0
}
 
! /^$|^[ \t]/ \
{
	nb_total++
	do
	{
		printf "* %s :  ", $1
		getline a < "/dev/stdin"
	} while (a != $2 && a != "c" && a != "q")
 
	if (a == $2) sc++
	else if (a == "c") print "  [correction]", $2
	else if (a == "q") exit
}
 
END {
	printf "—————\n %d bonnes réponses pour %d questions (%.f %%)\n\n", sc, nb_total, sc / nb_total * 100
}
fichier de test "finnois.txt" :
Code :
1
2
3
4
5
6
7
 
Finlande   	Suomi
1 + 1					2, même en finnois
 
mouais		eh oui.
	5dfsf
 fsdg.ikg
exécution :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
$ awk -f lt.awk finnois.txt
 
Entrez la traduction en finnois des expressions suivantes, ou :
 q pour quitter
 c pour afficher la correction
 
* Finlande :  Suomi
* 1 + 1 :  4
* 1 + 1 :  c       
  [correction] 2, même en finnois
* mouais :  eh oui.
—————
 2 bonnes réponses pour 3 questions (67 %)
Merci encore jmelyn.
sinuakin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 16h31   #6
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
Quelques précisions:
  • L'initialisation des variables est inutile: par défaut c'est zéro ou une chaine vide.
  • Les else if, bien que corrects ici, peuvent être omis. Cela simplifie la lecture.
  • Le problème que tu avais était l'indentation: il faut BEGIN { ou test { ou encore END { sur une même ligne. C'est pourquoi je mets un '\': cela permet de mettre l'accolade à la ligne.
__________________
Un problème bien posé est déjà résolu (H. Bergson).
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 17h19   #7
Invité de passage
 
Sinuakin Jean
Inscription : février 2010
Messages : 8
Détails du profil
Informations personnelles :
Nom : Sinuakin Jean

Informations forums :
Inscription : février 2010
Messages : 8
Points : 1
Points : 1
Merci.
Pour le point 3 je ne comprends pas, je pensais que l'on pouvait faire : { action } au lieu de : condition { action }, lorsqu'il n'y avait pas de condition.

dans mon premier code :
Code :
1
2
3
4
5
6
7
8
9
10
11
$1 == "" || $1 == " " { next } # (1) : condition {action}
 
puis :
 
{
	printf "%s: ", $1
	getline var < "/dev/stdin"
	# ... suite du code ...
}
&#8594; je me disais : pas de condition avant, donc exécuté tout le temps,
sauf quand la condition de (1) est remplie.
Plus besoin maintenant, mais c'est pour comprendre^^
sinuakin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 17h24   #8
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
Il faut:
Code :
1
2
3
4
5
6
7
8
9
10
awk '
BEGIN {
  # code
}
test {
  # code
}
END {
  # code
}
ou bien:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
awk '
BEGIN \
{
  # code
}
test \
{
  # code
}
END \
{
  # code
}
Edit: Et puis au niveau des conditions, ce n'est pas si simple. S'il n'y a aucune condition, le bloc sera exécuté systématiquement en plus des autres blocs conditionnels.
Code :
1
2
3
4
awk '
test_1 {bloc_1}
test_2 {bloc_2}
{bloc}' fichier
Ici, il est possible que, pour une certaine ligne, bloc_1, bloc_2 et bloc soient exécutés!

Re-edit: Flûte, ton bloc à toi était next. Donc logiquement ça devrait marcher. L'option -f du shebang n'est pas prise en compte. Pour l'instant je sèche...

Re-re-edit: Ça y est !!! Ce qui n'allait pas, c'était la manière d'appeler le programme: en utilisant la redirection '<', les données passent du fichier vers stdin
de la commande awk: awk -f test.awk < input_file. Or, tu utilises stdin dans le programme awk pour récupérer ce que l'utilisateur tape au clavier. D'où le téléscopage...
__________________
Un problème bien posé est déjà résolu (H. Bergson).

Dernière modification par jmelyn ; 14/02/2010 à 17h57.
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 18h18   #9
Invité de passage
 
Sinuakin Jean
Inscription : février 2010
Messages : 8
Détails du profil
Informations personnelles :
Nom : Sinuakin Jean

Informations forums :
Inscription : février 2010
Messages : 8
Points : 1
Points : 1
ok.

j'ai re-testé en partie l'ancien code, et il fonctionne :
Code :
1
2
3
4
5
6
7
8
9
10
 
#!/bin/awk
BEGIN {	FS = " *\t+ *" }
 
/^$|^[ \t]/ { next }
 
{
	printf "%s: ", $1
	getline var < "/dev/stdin"
}
J'avais donc fait une autre erreur, mais je n'ai plus le code en entier pour vérifier, donc mystère... enfin c'est résolu. Merci.
sinuakin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2010, 18h20   #10
Invité de passage
 
Sinuakin Jean
Inscription : février 2010
Messages : 8
Détails du profil
Informations personnelles :
Nom : Sinuakin Jean

Informations forums :
Inscription : février 2010
Messages : 8
Points : 1
Points : 1
Citation:
Re-re-edit: Ça y est !!! Ce qui n'allait pas, c'était la manière d'appeler le programme: en utilisant la redirection '<', les données passent du fichier vers stdin de la commande awk: awk -f test.awk < input_file. Or, tu utilises stdin dans le programme awk pour récupérer ce que l'utilisateur tape au clavier. D'où le téléscopage...
Ah voilà, bien joué =)
Merci pour tout.
sinuakin est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 07h04.


 
 
 
 
Partenaires

Hébergement Web