L'été est fini, c'est la rentrée ! Pour se remettre en forme, rien de tel qu'une revue des techniques de programmation en shell — ces techniques sont pour le shell de Bourne /bin/sh
mais peuvent être utilisées avec les shells compatibles qui permettent parfois des solutions plus faciles.
Sommaire
- Le dernier qui a fait ça chez nous est en train de sécher dans un faux plafond
- Programmation structurée
- Introspection
Note: comme ce texte est déjà très long, je propose que ceux qui ont aussi des choses à dire sur ce sujet le fassent dans des dépêches supplémentaires.
Le dernier qui a fait ça chez nous est en train de sécher dans un faux plafond
Si vous souhaitez faire don de votre corps à un taxidermiste, utilisez l'une des techniques suivantes dans votre programme: les backquotes, la commande echo ou bien analysez la sortie de la commande ls.
Les backquotes, backticks ou contr'apostrophes
N'écrivez jamais
candidates=`awk '{print($2)}' /etc/fstab`
mais plutôt
candidates=$(awk '{print($2)}' /etc/fstab)
parce que c'est plus facile à lire, plus facile de présenter correctement une longue fonction, plus facile à emboiter, bref les backquotes sont une technologie obsolète.
À propos, il est souvent plus facile et plus lisible de définir une fonction auxiliaire:
list_mount_points()
{
awk '
/^#/||/^$/{next}
{print($2)}
' /etc/fstab
}
candidates=$(list_mount_points)
Quand on a plus de place, c'est plus facile de mieux présenter son code, d'écrire un code plus robuste et le nom de la fonction décrit son rôle.
La commande echo
La fonction echo
n'est utile que pour afficher des messages de diagnostic, si la fonction printf
est disponible, il faut toujours préférer cette dernière, qui est plus puissante et plus facile à utiliser!
On peut par exemple imprimer des codes de caractère arbitraires:
TAB=$(printf '\t')
CR=$(printf '\015')
et imprimer correctement toutes les variables
attrape_nigaud='Pan!\cPan!'
printf '>>> %s <<<\n' "$attrape_nigaud"
echo "$attrape_nigaud"
L'appel à printf
est bien défini mais pas celui à echo
qui produit Pan!
sous Debian/Jessie mais Pan!\cPan!
sous FreeBSD.
Rappelons la définition bien pratique de la fonction eprintf
permettant d'écrire sur la sortie d'erreur standard :
eprintf()
{
>&2 printf "$@"
}
Analyse de la sortie de la commande ls
En bref la règle d'or est que la commande ls
sert uniquement pour l'utilisation interactive du shell, dans le cas d'un script shell, on utilise soit le globbing soit la commande find
en conjonction avec xargs
.
La raison est que la commande ls
est inutilisable dès que les fichiers contiennent des caractères exotiques. Il est inutilement difficile d'analyser correctement la sortie de ls
et il est tellement facile d'utiliser un globbing:
for file in $(ls); do ← Exemple à ne pas suivre!
printf '%s\n' "$file"
done
est corrigé en
for file in *; do
printf '%s\n' "$file"
done
ou bien, pour des recherches plus compliquées:
NUL=$(printf '8f872742767daab9354ff276b9d5504afb94060400')
find /path/to/dir -type d -name '* *' -print0 \
| while IFS="$NUL" read file; do
printf '%s\n' "$file"
done
L'information fournie par ls -l
est facilement accessible avec stat
.
Construction de la ligne de commande
Un problème analogue à celui de l'analyse la sortie de la commande ls
est celui de la préparation de l'appel à une commande du type
utility -file file1 -file file2
La version vite-fait mal fait consiste à dire:
argv=''
for file in *; do
argv="$argv -file $file" ← Exemple à ne pas suivre
done
utility $argv
Évidemment, comme vos noms de fichiers utilisent un codage binaire où le ' ' représente 0
et le retour à la ligne représente 1
, tout va de travers! La façon indestructible d'appeler utility est d'utiliser xargs -0
comme dans:
job_strategy()
{
local file
for file in *; do
printf '-file\000%s\000' "$file"
done
}
job_strategy | xargs -0 utility
Programmation structurée
Les débutants commettent souvent l'erreur consistant à vouloir répliquer les structures d'enregistrement (les struct
de C ou C++, les record
de Pascal) dans des variables du shell.
Mais ce n'est pas comme ça que ça marche!
Un bonne règle pour l'organisation des données dans un programme shell est de de n'utiliser les variables que pour les objets du monde UNIX: chemins de dossiers, chemins de fichiers, pids, uids, etc. Tout le reste, en particulier les structures d'enregistrement, va dans des fichiers ou des pipes, sous forme de table séparée par des |
ou par des caractères ASCII US=$(printf '\037)
pour ceux qui vivent au pays des gens utilisant |
dans leurs données — et les traitements complexes sont effectués par des filtres. Si ça ne convient pas à votre programme, changez de langage, utilisez OCaml, Perl ou Python. Bien-sûr, tout le monde n'est pas de cet avis, en particulier, les maîtres de la programmation shell. Les maîtres ont une caractéristique importante qui démultiplie leur faculté de jugement bien au delà de ce que peut imaginer un débutant : ce sont des maîtres. Si vous êtes un débutant, ne vous laissez pas impressionner par les maîtres qui ont déjà écrit un interpréteur Scheme en sed
et utilisent la commande printf
pour insérer du code shell auto-modifiant dans le noyau Linux. N'hésitez pas à utiliser un autre langage pour résoudre votre problème.
Exemple du renommage de fichier
Illustrons cette technique sur l'exemple classique du renommage de fichier en masse. La procédure finale se décompose en
job_select | job_strategy | job_perform
On a trois fonctions correspondant aux étapes suivantes:
-
job_select
prépare une liste des fichiers à renommer ; -
job_strategy
prépare une donnée tabulaire avec deux colonnes, l'une contenant le nom initial, l'autre le nouveau nom ; -
job_perform
qui fait la modification finale.
On fait l'hypothèse paranoïaque que les caractères /n
et |
n'apparaîssent pas dans les noms de fichiers. Si ce n'est pas le cas, utilisez un vrai langage de programmation — mais les maîtres, eux, savent comment faire!
La fonction job_select
ressemble typiquement à
job_select()
{
find /path/to/directory -name '*@!*' -print0
}
La commande job_strategy
prépare un plan de travail:
job_strategy()
{
sed -e'
h
s/@!/--censored--/g
H
x
s/\n/|/'
}
Ceux qui n'ont pas encore écrit d'interpréteur Scheme en sed
peuvent lire le walkthtough suivant, en anglais parceque je ne sais pas dire walkthrough ou pattern space en français et que personne n'en comprendrait les traductions:
h Save pattern space to hold space
s/…/…/ Edit the name in the pattern space
H Append the edited name to the hold space
x Exchange hold and pattern space
s/\n/|/ Replace the newline by a field separator
Bien-sûr on peut utiliser n'importe quel autre langage que sed
pourvu qu'on soit capable d'écrire un filtre transformant
Quel @! de patron
en
Quel @! de patron|Quel --censored-- de patron
Finalement la procédure de renommage ressemble à
job_rename()
{
local oldname newname
while IFS='|' read oldname newname; do
if [ "$oldname" = "$newname" ]; then
printf 'Skipping %s\n' "$oldname" >&2
else
mv "$oldname" "$newname"
fi
done
}
Oui je sais, on peut faire la même chose avec rename '/@!/--censored--/' *
ou avec la commande @!
de zsh
, mais il s'agit d'un exemple un peu scolaire pour illustrer la méthode.
Un effet secondaire très appréciable de cette organisation est qu'on peut tester chaque morceau individuellement et faire du mocking
facilement.
Ainsi, si au lieu d'exécuter job_select | job_strategy | job_perform
à la fin de mon script j'utilise simplement job_select
je peux m'assurer que la liste de fichiers est correcte, et avec job_select | job_strategy
je peux vérifier que mon plan de travail est correct. Aussi, je peux créer des données artificielles pour tester job_strategy
, par exemple
mock_issue_42_job_select()
{
cat <<'EOF'
This is an example of pathological input causing issue 42
EOF
}
mock_issue_42_job_select | job_strategy
Exemple de l'analyse de contenu de fichier vidéo
Un exemple plus amusant est celui de cette fonction, issue d'un programme de vidéothèque que j'ai écrit en shell.
# cinema_identify FILE
# Identify the given file.
#
# Identifying the file causes a content index to be dumped on
# stdout. This content index describes the content of the file.
# There is two types of records, for Tracks and for Attachments.
#
# Track|INDEX|TYPE|CODEC
# Attachment|INDEX|TYPE|SIZE|FILENAME
#
# An output example is:
#
# Track|0|video|V_MPEG4/ISO/AVC
# Track|1|audio|A_VORBIS
# Track|2|audio|A_VORBIS
# Track|3|audio|A_VORBIS
# Track|4|subtitles|S_VOBSUB
# Track|5|subtitles|S_VOBSUB
# Attachment|1|image/jpeg|93405|+POSTER
# Attachment|2|text/plain|54|+INDEX
cinema_identify()
{
env LANG=C mkvmerge --identify "$1" \
| sed -e '
s/'//g
/^File/{
d
}
/^Track/{
s/ ID /|/
s/: /|/
s/ (\(.*\))/|/
}
/^Attachment/{
s/ ID /|/
s/: type /|/
s/. size /|/
s/ bytes, file name /|/
}'
}
Cette commande prend un fichier vidéo en argument et écrit sur la sortie un truc du genre
Track|0|video|V_MPEG4/ISO/AVC
Track|1|audio|A_VORBIS
Track|2|audio|A_VORBIS
Track|3|audio|A_VORBIS
Track|4|subtitles|S_VOBSUB
Track|5|subtitles|S_VOBSUB
Attachment|1|image/jpeg|93405|+POSTER
Attachment|2|text/plain|54|+INDEX
Bien-sûr dans le vrai script, le script sed
est dans un fichier auxiliaire pour, pour le test et la lisibilité.
Voici comment traiter de façon polymorphe cette sortie:
cinema_polymorph_example()
{
local field_type rest
while IFS='|' read field_type rest; do
IFS='|' set -- $rest
case "$field_type" in
Track) process_track "$@";;
Attachment) process_attachment "$@";;
*) >&2 printf 'Unknown field type %s\n' "$field_type";
exit;;
esac
done
}
Dans cet exemple chaque ligne commençant par Track
est traitée par process_track
et chaque ligne commençant par Attachment
est traitée par process_attachment
.
Liste des commandes travaillant avec des données tabulaires
Voici une liste pêle-mêle de fonctions travaillant sur des données tabulaires.
awk(1) - pattern-directed scanning and processing language
sed(1) - stream editor
paste(1) - merge corresponding or subsequent lines of files
join(1) - relational database operator
comm(1) - select or reject lines common to two files
cut(1) - cut out selected portions of each line of a file
lam(1) - laminate files
sort(1) - sort or merge records (lines) of text and binary files
uniq(1) - report or filter out repeated lines in a file
Il faut bien noter que toutes ces fonctions n'utilisent pas forcément les mêmes options pour définir le délimiteur.
Introspection
Oui, vous lisez bien, le shell permet de faire l'introspection, de façon limitée. Par exemple, voyons comment définir une mini base de données de repositories git à sauvegarder:
project1_repo='/var/git/project1.git'
project1_refs='master v1.0 v2.0'
project2_repo='/var/git/project2.git'
project2_refs='master v1.0 v2.0'
gitdb_list()
{
set | sed -n -e 's/_repo$//p'
}
gitdb_tabular()
{
local repo dir refs
gitdb_list | while read repo; do
eval printf '%s|%s|%s\n' "$repo" "\$${repo}_dir" "\$${repo}_refs"
done
}
gitdb_backup()
{
local repo dir refs
gitdb_list | while read repo dir refs; do
git bundle create "/backup/$repo" "$repo_dir" HEAD $refs
done
}
Dans ce cas particulier, je préfèrerais utiliser directement une base de données tabulaires, mais si pour une raison ou une autre on ne devait utiliser que des variables shell pour transmettre l'information alors cette technique est utilisable.
Aller plus loin
- ShellCheck (en ligne ou localement) (1273 clics)
- Obsolete and deprecated syntax (Bash Hackers wiki) (826 clics)
# Muchas gracias!
Posté par FantastIX . Évalué à 10.
Merci pour ce guide. Je me rends compte que j'ai du bol de n'être pas encore en train de sécher dans un faux-plafond. Mais, tout compte fait, il y a deux raisons à ça: 1) je suis seul à scripter sous Linux dans la boîte et 2) y a pas de faux plafond.
Ceci dit, la théorie et les règles, c'est bien. Mais écrire des scripts SHELL qui tournent aussi bien sous *NIX que Mac OS, par exemple, ça rend les règles plus difficiles à suivre. Surtout en raison des différences entre les outils, genre sed et tar, pour ne citer qu'eux.
Cette dépèche est à accrocher en post-it sur le bureau.
(Hein? Comment ça, trop de post-it?)
[^] # Re: Muchas gracias!
Posté par barmic . Évalué à 4.
Pas tant que ça, les extensions GNU sont surtout utiles pour des usages interactifs ou sont assez peu connu.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Muchas gracias!
Posté par FantastIX . Évalué à 3.
J'en ai aucune idée en fait, je ne suis pas encore assez avancé, j'imagine. Les expériences que j'ai eues concernent notamment les options. Par exemple, '-r' rend les expressions régulières bien plus lisibles avec sed sous Linux. Mais avec OSX, c'est '-E'. Je ne me souviens plus des détails avec tar mais je sais que j'ai séché pas mal de temps avant de trouver.
[^] # Re: Muchas gracias!
Posté par SlowBrain (site web personnel) . Évalué à 3.
Moi qui viens de passer l'après midi à devoir «convertir» un scrip SHELL Linux en VBScript car seules les machines de l'entreprises (donc sous Windows) sont autorisée sur le réseau … je me dit que j'aimerais bien n'avoir a faire qu'as MacOS X
[^] # Re: Muchas gracias!
Posté par barmic . Évalué à 7.
PowerShell est probablement bien plus intéressant à utiliser.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Muchas gracias!
Posté par lolop (site web personnel) . Évalué à 2.
GNUWin32 ?
(enfin, si tu as l'autorisation d'installer des logiciels)
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Muchas gracias!
Posté par SlowBrain (site web personnel) . Évalué à 1.
En entreprise c'est un droit qui est assez rare, et que je n'ai pas. C'est aussi (mis à part le fait que ce soit un système libre) l'un des gros avantage que j'avais à utiliser ma machine : je peu y faire ce que je veux.
Pour le choix entre PowerSchell et VBScript, j'ai juste pris celuis qui me semblais dans l'instant le plus correspondre à mes besoins.
[^] # Re: Muchas gracias!
Posté par Babelouest (site web personnel) . Évalué à 5.
Si c'est pas trop tard (et bien que off-topic), reconsidère PowerShell, il a vraiment beaucoup plus d'atouts, pour peu que tu sois sur des windows plus récents que XP…
[^] # Re: Muchas gracias!
Posté par SlowBrain (site web personnel) . Évalué à 1.
Rien n'est jamais trop tard, quelqu'un aurais un bout de guide pour le grand débutant libriste linuxien a propos de cette technologie ?
J'ai l'impression de m'y retrouver comme pour la première fois face à un terminal sur une mandake 8.
Après le but est de faire du libre (QGis - PostgreSQL - SQLite) mais sous Windows, donc ca touche quand même le libre.
[^] # Re: Muchas gracias!
Posté par pasBill pasGates . Évalué à 3.
http://powershelltutorial.net/
# Construction de la ligne de commande
Posté par barmic . Évalué à 10.
Pour la construction de la ligne de commande, il faut aussi parler de l'utilisation de
--
pour déterminer la fin des options, on ne devrait jamais voir :mais plutôt
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Construction de la ligne de commande
Posté par Jiehong (site web personnel) . Évalué à 10.
C'est quand même mieux de dire pourquoi :
Le double-tiret permet d'indiquer la fin des options, et le début des paramètres. Cela permet d'éviter d'interpréter des paramètres en tant qu'options.
Exemple :
[^] # Re: Construction de la ligne de commande
Posté par tyoup . Évalué à 3.
Bah oui les blagues sont beaucoup plus drôles quand on les explique ;)
# Liste des commandes travaillant avec des données tabulaires
Posté par barmic . Évalué à 10.
Personnellement je ne les connais pas toutes mais il est intéressant souvent de travailler avec un langage qui ferra tout le boulot. Notamment
awk
est vraiment puissant et il est généralement inutile d'utilisergrep
oused
devant ou derrière unawk
ce dernier faisant très bien le boulot.Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Liste des commandes travaillant avec des données tabulaires
Posté par Michaël (site web personnel) . Évalué à 7.
La puissance d'expressivité de
awk
est surprenante, même avec un niveau intermédiaire on arrive à écrire rapidement des programmes très intéressants et étonnamment courts.C'est indéniablement un des programmes outil qui, à mon sens, doivent faire partie de la trousse à outil de toute personne utilisant un système UNIX — au même titre que le shell et make.
[^] # Re: Liste des commandes travaillant avec des données tabulaires
Posté par barmic . Évalué à 6.
Il m'arrive régulièrement de faire des scripts
awk
uniquement (avec le shbang#!/usr/bin/awk -f
). J'avais notamment réécris en moins de 10 lignes un programme java d'un collègue qui analysait des logs ssh…Moi je trouve assez amusant la manière de programmer en
awk
qui fait penser à de la programmation évènementielle ou un parseur SAX.Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Liste des commandes travaillant avec des données tabulaires
Posté par Pierre Jarillon (site web personnel) . Évalué à 3.
Oui, awk est très intéressant mais à mon avis il vaut mieux le réserver à des programmes courts.
Au delà d'une ou deux dizaines de lignes, les erreurs dans le programme deviennent difficiles à gérer.
Alors, je préfère écrire un filtre en C. C'est plus facile à lire et à maintenir.
[^] # Re: Liste des commandes travaillant avec des données tabulaires
Posté par barmic . Évalué à 5.
Ouai, bof bof. Le C pour gérer des chaines de caractère c'est vraiment pas génial, là où tout langage de script te fais le café (perl en tête).
Personnellement je trouve que sortir du C pour ça est la majorité du temps une très grosse perte de temps.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Liste des commandes travaillant avec des données tabulaires
Posté par lasher . Évalué à 4.
Bon, je préfère Perl pour ajouter des filtres perso (quand un truc genre grep/sed/awk devient compliqué), mais il ne faut pas oublier qu'écrire un programme en C ne signifie pas forcément « écrire un programme en C en ne se servant que de
string.h
comme base » : tu peux parfaitement utiliser des bibliothèques (par exemple, la bibliothèque de regexps du projet GNU), et simplifier grandement ton code plutôt qu'utiliserstrtok
. De même, tu peux parfaitement avoir commencé à construire un ensemble de wrappers (genresmalloc
qui va crasher si y'a un problème d'allocation, et qui te permet de ne pas te soucier de la gestion d'erreur,sread
pour gérer les erreurs et le besoin de répéter l'opération en cas d'interruption, etc.) qui vont simplifier grandement ton code et le rendre suffisamment lisible pour te concentrer sur l'essentiel : l'algorithme.J'insiste, je pense qu'un langage de plus haut niveau (Perl/Python/Ruby/Lua/Bla) serait sans doute meilleur pour gérer ce genre de choses, mais je pense aussi que le meilleur outil pour faire un programme de taille raisonnable est celui qu'on maîtrise bien.
[^] # Re: Liste des commandes travaillant avec des données tabulaires
Posté par tyoup . Évalué à 3.
à condition de faire alias awk=perl avant :)
# echo
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 10.
Et qui est surtout portable, contrairement à
echo
, dont les mises en œuvre diffèrent de façon incompatible, entre celles intégrées aux shells et celles indépendantes ! Regardez notamment son option -e…[^] # Re: echo
Posté par barmic . Évalué à 9.
Il faut aussi rappeler que s'il s'agit de logging la commande
logger
est faite pour ça.Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# Un petit mot sur les performances
Posté par barmic . Évalué à 10.
Le shell (quelque soit le shell) n'est pas performant, c'est mou que ça en peu plus (même dash) par conception. Pourtant on peut faire des programmes très performants en shell !
Il y a 2 grandes familles de parallélisme en shell qui sont très simples à faire.
Les pipelines, tout le monde les connais on les as tous déjà vu. Il y a des exemples plus hauts de programmes l'utilisant. On découpe un traitement en plusieurs étapes et chaque processus s'occupe d'une partie de ce traitement. On peut voir ça comme une programmation fonctionnelle. Chaque bout de programme est un filtre et a une entrée bien définie et une sortie bien définie (par exemple son entrée c'est des noms de fichiers et ça sortie c'est une sommes de contrôle un espace puis le nom du fichier).
Le parallélisme à la
xargs
(je connais pas le nom du paradigme), là il s'agit d'exécuter le traitement pleins de fois en parallèle. Il faut savoir qu'il n'y a pas quexargs
pour faire ça.find
le fait aussi très bien avec le terminateur+
à la place de;
en fin de commande. Il y a aussi gnu parallel, mais il est rarement installé.L'énorme avantage de ces modes c'est qu'on ne lance pas des milliers de processus (notamment avec les pipes) ce qui est contre productif.
Si j'ai des conseils à donner sur les performances en shell, je conseil de regarder en priorité 3 choses :
fork
, lancer pleins de fois le même programme c'est très lourd, il faut généralement voir pour lui donner toutes les données d'un coup ou voir pour le lancer en arrière plan et pouvoir lui fournir les données au fur et à mesuresort
va totalement détruire les performance des pipes parce qu'il va attendre d'avoir toutes les données avant de pouvoir commencer sont travailTous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Un petit mot sur les performances
Posté par Michaël (site web personnel) . Évalué à 3.
Excellent complément(s)!
Je confirme totalement, c'est d'ailleurs une raison supplémentaire pour déléguer tous les traitements complexes à des filtres.
Je m'étais amusé à faire de la POO en shell, c'est à dire à implémenter un mécanisme d'héritage. En gros:
En appelant copieusement la fonction
eval
et en regardant sur le dossier plusieurs fois avant chaque appel de méthode, on arrive à faire ramer copieusement n'importe quelle machine!Est-ce que par hasard tu connais des outils qui vont un pas plus loin et font du parallélisme distribué? Par exemple qui récupère une liste de comptes SSH et lance des programmes sur l'hôte distant?
[^] # Re: Un petit mot sur les performances
Posté par barmic . Évalué à 3.
Pas surprenant, je l'ai pas mis plus haut mais celui qui met un
eval
dans un script shell, doit mettre 15 lignes pour expliquer pourquoi il est obligé de faire ça.Comme ça, non. Tu peux jouer un peu avec fabric, mais on quitte le monde du shell. Perso je pencherais plus pour faire quelque chose à coup de netcat/socat, mais ça doit demander pas mal de boilerplate. Pour arriver à quelque chose.
Bien sûr tu peut aussi simplement faire des
ssh alias cmd
1 qui marche bien et qui te permet de récupérer le résultat.j'utilise des alias défini dans mon
~/.ssh/config
généralement, ça me permet d'avoir du coté script shell de la logique uniquement de la logique et du coté fichier de configuration ssh tout ce qui est spécifique à l'environnement ↩Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Un petit mot sur les performances
Posté par François (site web personnel) . Évalué à 3.
Peut être GNU parallel
[^] # Re: Un petit mot sur les performances
Posté par Michaël (site web personnel) . Évalué à 2.
In der Tat: GNU parallel is a shell tool for executing jobs in parallel using one or more computers.
[^] # Re: Un petit mot sur les performances
Posté par serge_sans_paille (site web personnel) . Évalué à 2.
http://taktuk.gforge.inria.fr/
[^] # Re: Un petit mot sur les performances
Posté par barmic . Évalué à 4.
Autre chose coté performance, il vaut mieux ne pas trop croire et plutôt tester. J'ai eu de jolies déconvenues avec des script
zsh
dans les quels j'utilisaiszargs
(un outils pour utiliser un équivalent àxargs
avec les globbings étendus) qui est assez peu efficace contrairement à ce que j'espérais.Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Un petit mot sur les performances
Posté par Le Gab . Évalué à 3.
Cela dépend aussi fortement de la méthode. Il y a un "framework" Shell créé, éprouvé et utilisé à des fins de traitement de données massives qui s'appelle Unicage.
Ils utilisent les concepts UNIX et ses outils à leur paroxysme. Il y a certes 2 ou 3 binaires custom et optimisés mais on peut se contenter d'utiliser les alternatives originales (join, date,…) si on ne recherche pas la vitesse ultime.
Ça reste un peu austère, informatique japonaise oblige, mais il y a du très bon.
[^] # Re: Un petit mot sur les performances
Posté par Matthieu Moy (site web personnel) . Évalué à 3.
Euh, pas le mien en tous cas.
find ... -exec commande {} +
permet simplement d'exécuter une seule commandecmd fichier1 fichier2 ...
(éventuellement découpée en plusieurs commandes s'il y a plus de fichiers que la limite de nombre d'arguments autorisée) au lieu de fairecmd fichier1; cmd fichier2; ...
. C'est plus rapide parce que ça réduit considérablement le nombre de fork+exec, mais pas pour le parallélisme.J'ai peut-être raté un truc, mais en tous cas la page de man de ma version de find ne contient pas le mot « parallel ».
# Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 6.
Bonjour à tous,
Cela fait plaisir de voir d'excellents conseils de programmation sur un truc aussi ancien que le shell :)
Et je suis globalement d'accord, sauf sur la punition, il serait plus judicieux de lui supprimer son PC sous linux et de lui passer une tablette surface sous Windows 8 :) (2 jours devraient suffir)
Sinon juste un petit truc : avant de vous lancer comme des fous dans l'awk, le join paste et consort … il est bien souvent beaucoup plus judicieux d'utiliser des langages plus adaptés comme le python, le ruby le perl (par exemple …)
Même si cela ressemble a un fusil pour tuer les mouches, dans la durée les langages de scripts + une petite base comme sqlite sont plus facile à utiliser, a debugger et à modifier que du shell.
Voire même du fichier ascii a plat comme intermédiaire.
Par contre, je ne suis pas pour reléguer le shell juste aux bidouilles, aux trucs vite fait. tout dépend du projet. Parfois le mélange des deux donne d'excellents résultats.
Mais je n'ai pas de recette toute faites pour dire ça c'est mieux en shell, tel autre en python.
Sinon je ne connaissais pas lam (laminate), comme quoi même après 25 ans de shell on en apprend toujours :)
Merci
[^] # Re: Presque d'accord ...
Posté par barmic . Évalué à 6.
Il y a des cas simples et clairement en faveur de l'un des deux. Si tu lance des programmes externes le shell est ton amis, si tu manipule beaucoup le système de fichier le shell est ton amis, si tu fais pas mal de calcul le shell est ton pire ennemis,…
Pour le reste ça dépend, des connaissances de celui qui développe, de la plateforme cible, etc
Personnellement, il faut arriver à un gros niveau de complexité pour que je quitte le shell. Mais je n'hésite pas à prendre
perl
comme unawk
amélioré (sauf si je fais trop d'aller-retour entre le shell etperl
).Souvent le shell est mal maitrisé et t'a l'air d'un gourou dès que tu sort quelque chose d'un peu propre (et je ne parle pas d'
awk
…).Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 4.
Je trouve que la question suffisamment subtile pour ne pas recevoir une réponse tout à fait tranchée. Bien-sûr utiliser un vrai langage et une vraie base de données a de gros avantages, mais a aussi quelques inconvénients.
L'inconvénient le plus important de cette approche est que cela demande un effort de déboguer les I/O dans la base de données alors que dans la version “zen du shell” il suffit de débrancher un tube pour voir ce qui en sort. De plus l'opérateur de composition de tubes (le
|
) encourage une structuration très claire du programme et n'a pas toujours d'équivalent dans les autres langages de programmation. (À part bien sûr le|>
de OCaml!)Ceci dit bien connaître
OCamlun autre langage comme Python, Perl ou Ruby est bien-sûr un avantage énorme pour développer rapidement des traitements pas encore existants en shell.Néanmoins, bien connaître
awk
est tout de même une compétence dont il serait dommage de se passer quand on utilise un système UNIX.[^] # Re: Presque d'accord ...
Posté par zurvan . Évalué à 2.
on peut utiliser perl avec des tubes | par exemple :
printf "Emacs c'est le meilleur éditeur de texte\n" | perl -pe 's/Emacs/Vim/'
« Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 8.
Je parlais plutôt de l'intérieur du programme… Est-ce qu'il y a un pipe dans
perl
qui permettrait de combiner deux fonctions?C'est inutilement compliqué, on peut simplifier en
[^] # Re: Presque d'accord ...
Posté par zurvan . Évalué à -1.
question intéressante, par contre c'est vrai que le tube c'est pour associer des programmes généralement disparates (ou chaîner plusieurs traitements du même programme). Dans les autres langages, il y a des possibilités un peu similaire (même si moins graphiques) pour combiner plusieurs fonctions, par exemple récupérer un paramètre d'une fonction et la renvoyer à une autre.
quitte à simplifier, autant utiliser directement vim pour éditer le texte d'origine… ;)
« Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher
[^] # Re: Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 4.
Pour communiquer à l'intérieur de ton programme rien ne vaut … les variables :)
le pipe est fait pour la communication entre programme ou processus
[^] # Re: Presque d'accord ...
Posté par lolop (site web personnel) . Évalué à 4.
En Perl, je ne sais pas, mais en Python il y a plusieurs projets qui reprennent la syntaxe du Pipe avec
|
pour enchaîner des traitements sur des flux de données:Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 1.
Ne faire qu'un chose et le faire bien :) …
Oui tout a fait d'accord, il faut connaître awk AVANT de faire du perl et du python.
Mais bon de plus en plus de personnes ne savent même pas que l'on peut scripter des commandes.
Et c'est bien dommage.
[^] # Re: Presque d'accord ...
Posté par chimrod (site web personnel) . Évalué à 3.
Imaginons que tu ais trois fonctions :
Ces trois fonctions peuvent s'assembler pour afficher le contenu fichier.
Une première manière est de faire :
Or, |> est une fonction définie comme ça :
C'est à dire qu'elle prend un type x, une fonction f, et en inverse l'application. Par exemple cela permet d'écrire :
Bien sûr ça n'a pas beaucoup de sens dans l'exemple ci dessus, mais ça permet de réécrire le premier bloc de code de la manière suivante :
Et voilà :)
[^] # Re: Presque d'accord ...
Posté par barmic . Évalué à 3.
Je trouve pas le gain de ce genre de choses démesuré. L'intérêt du pipe sur les appels de méthode chainé c'est le parallélisme. Pour le reste c'est plus du sucre syntaxique.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Presque d'accord ...
Posté par chimrod (site web personnel) . Évalué à 3.
C'est du sucre syntaxique ! Nous sommes d'accord.
Il existe d'autres structures plus évoluées (quelqu'un a dit monade ?), selon que l'on veut du parallélisme synchrone, asynchrone, ou encore du multiprocessing…
Tout ne peux être exprimé à travers la syntaxe seule…
[^] # Re: Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 1.
C'est tout aussi clair et sans symbole ésotérique difficile a obtenir sur de l'azerty :)
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 2.
Je préfère la version qui ne parle pas de
f
ou dedata
qui ne véhiculent aucune information sur le programme.Bien-sûr un exemple de trois lignes n'est pas forcément ce qu'il y a de plus probant, mais en pratique cet opérateur est extraordinairement pratique.
Peut-être, mais les maîtres utilisent un clavier QWERTY! ;)
Blague à part, pour la programmation, c'est bien mieux qu'un AZERTY ou un QWERTZ, je n'utilise plus que ça depuis 8 ans, pas question de changer!
[^] # Re: Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 1.
Tout a fait d'accord pour le QWERTY :)
pas pour le reste, j'aime bien les variables ;-)
par contre Ocaml m'a l'air très intéressant, a voir c'est une horreur
beaucoup d'habitudes doivent changer (# ~ et :: par exemple), et un clavier qwerty doit être nécessaire :)
Par contre pour le reste, cela a l'air plus que bien … Merci d'avoir suscité ma curiosité
j'ai peut être trouvé un nouveau jouet.
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 1.
OCaml est un langage extraordinaire! Les caractéristiques clefs:
Le typage fort, qui me permet de placer assez d'invariants de mon code dans le système de types pour trouver la plupart de bogues pendant la compilation. En pratique il ne reste plus que les erreurs intelligentes!
L'aspect fonctionnel. Plus jamais une boule
for
tu n'écriras! (Mais, bon, si tu aimes bien les variables…☺)La simplicité du modèle de compilation. Un bon programmeur C peut estimer facilement la complexité à l'éxécution du code OCaml.
La relative facilité de lecture! Oui. À côté de Haskell par exemple, OCaml est très facile à lire!
[^] # Re: Presque d'accord ...
Posté par anaseto . Évalué à 4.
Moi j'écris des boucles
for
en OCaml de temps en temps… :) C'est d'ailleurs ce que j'aime dans ce langage, c'est que malgré le côté très rigoureux du système de types et l'aspect fonctionnel, tu peux quand même, quand c'est opportun, utiliser un langage assez impératif, avec des variables (les références), des tableaux mutables etc. Toutes ces choses sont assez alambiquées à faire en Haskell en comparaison, et c'est en fait pour ces choses là que Haskell devient moins facile à lire parfois.[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 2.
Et c'est opportun pour faire de l'IO, surprise surprise. Pour une question sur SO j'ai fait une petite comparaison en OCaml entre un style d'output impératif traditionnel et le style en monades: conclusion le style impératif est plus rapide.
Si je trouve Haskell si difficile à lire c'est qu'on peut définir des macros qui ont apparemment plein de pouvoir magiques, notamment à réécrire les
do…
en choses moins inoffensives qu'elles n'en ont l'air.[^] # Re: Presque d'accord ...
Posté par chimrod (site web personnel) . Évalué à 2.
Tu ne compares pas vraiment la même chose. Ici, tu crées un environnement dans lequel le fichier reste ouvert tant que la variable f est accessible. J'avais pris l'exemple du fichier pour montrer le chaînage des fonctions parce que c'est plus parlant que f, g et h mais tu as également des structures pour construire des environnements comme celui que tu viens d'écrire en python.
[^] # Re: Presque d'accord ...
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 3.
Depuis quand utilise-t-on tant de parenthèses en Caml ?
Quant à cette fonction, elle est visiblement infixe, ce qui vaut la peine d'être mentionné tout de même !
[^] # Re: Presque d'accord ...
Posté par anaseto . Évalué à 4.
Sans parenthèses:
serait un appel a la fonction
print_line
avec trois arguments. Dans l'exemple les seules parenthèses inutiles sont celles autour de "mon_fichier.txt".Et, en OCaml, hormis quelques built-in, les seules fonctions infixes sont celles formées uniquement de symboles, et elles sont déclarées avec des parenthèses autour
let (<|) = ...
. Il n'y a pas de flexibilité à ce niveau.[^] # Re: Presque d'accord ...
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 4.
Oui, j'avais compris ça.
Et il n'y en a pas forcément besoin d'ailleurs. Mais merci pour l'info, j'ignorais cela, et je dois dire que ça m'avais manqué, la possibilité de définir des opérateurs infixes.
Mes expériences avec Caml datent un peu, mais j'aime toujours bien ce langage !
[^] # Re: Presque d'accord ...
Posté par zurvan . Évalué à 2.
awk et sed c'est pas mal, mais pour certaines regex, je trouve effectivement plus pratique d'utiliser perl (sans doute aussi parce que je ne suis pas un maître).
À noter l'outil txt2regex permet d'aider à construire des regex pour perl, php, python, sed… (20 programmes en tout, y compris OpenOffice, pour les règles de parefeu sans doute ;) )
« Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher
[^] # Re: Presque d'accord ...
Posté par anaseto . Évalué à 3.
Disons que tant que c'est des regex simples, awk et sed font bien le travail, mais dès que tu as besoin d'utiliser des classes unicode, d'écrire sur plusieurs lignes tes regexs pour plus de lisibilité, de contrôler plus finement la façon de matcher (pour de l'analyse lexicale par exemple avec le modifieur
\G
en perl), … ce n'est juste plus possible avec awk et sed. Et avec awk, même les backreferences, qui sont bien pratiques, ne sont pas portables et n'existent que dans gawk (que je sache).[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 3.
Je suis tout à fait d'accord avec toi: dès qu'on sort de l'extraction pure de données et qu'on a besoin “ne serait-ce” que d'UNICODE¹
awk
montre ses limites. Quand à GNU Awk… pourquoi ne pas utiliser directement Perl? :-) Ce qui est intéressant dans le Awk “de base” c'est qu'il offre une balance très claire entre performance et petite taille d'un côté et expressivité de l'autre. Vu de loin, GAwk est un peu feature bloated — mais a l'immense intérêt d'être un Awk portable — et j'aurais tendance à passer directement à Perl. (Cette position pas hyper subtile n'engage que moi!)¹ J'ai guillemetté à cause de la taille moyenne d'une bibliothèque supportant UNICODE de façon poussée ou quasi complète.
[^] # Re: Presque d'accord ...
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 7. Dernière modification le 23 septembre 2014 à 09:15.
Un équilibre, en français. Ou mieux, vu la phrase, un compromis. Une balance, ce n'est qu'un instrument qui sert à mesurer la masse.
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 6. Dernière modification le 23 septembre 2014 à 09:37.
Merci, le pire c'est que je ne me rends plus compte que j'écris des choses comme ça! Je ne vis plus en France depuis presque six ans et avec le tant qui passe j'ai de plus en plus de sympathie pour Jean-Claude van Damme! ☺
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 9.
Avec le tant va,
toussant va…
[^] # Re: Presque d'accord ...
Posté par Ignatz Ledebur . Évalué à 0.
Unicode sera quasi-toujours implémenté en UTF-8 au niveau du shell (pour la compatibilité avec l'ASCII) et pour le reste, il y a toujours la commande standard iconv. Quant à Gawk, s'il est vrai qu'il grossit de manière inquiétante, il demeure au moins aussi performant que la version de Kernighan, y compris en UTF-8 (non supporté par cette dernière — mais la plupart du temps, à part pour la longueur des chaînes dans le formatage des sorties, on s'en moque, car il n'y a aucune raison d'employer des caractères non-ASCII comme clés de formatage interne, bien au contraire).
[^] # Re: Presque d'accord ...
Posté par Antoine . Évalué à 3.
La gestion de l'unicode dans les expressions régulières ne se limite pas aux caractères litéraux, mais impacte les métacaractères type
\w
.[^] # Re: Presque d'accord ...
Posté par Ignatz Ledebur . Évalué à -1.
C'est vrai, mais dans le cadre du shell, ça reste du contenu, pas de la syntaxe. Ce que je veux dire, c'est que tu prennes du HTML, du Mardown, du LaTeX, du Groff, de l'INI ou n'importe quel fichier de configuration, tu n'as besoin que de l'ascii pour en faire l'analyse syntaxique. Après, que tu puisses avoir besoin d'unicode pour l'analyse du contenu introduit par l'utilisateur, on est d'accord, mais on est alors au-delà de la stricte analyse syntaxique (en HTML, ça reviendrait à analyser du #PCDATA, ce pourquoi effectivement le shell/awk n'est probablement pas l'outil le plus adapté).
[^] # Re: Presque d'accord ...
Posté par Ignatz Ledebur . Évalué à 1.
(Au passage, ce que tu pointes précisément a en fait plus à voir avec la capacité à supporter la locale qu'avec unicode, une locale avec un encodage 8bits posant les mêmes difficultés quant à l'usage de classes de caractères « nommées ».)
[^] # Re: Presque d'accord ...
Posté par Antoine . Évalué à 2.
Le consortium Unicode a normalisé les classes de caractères dans les expressions régulières :
http://www.unicode.org/reports/tr18/#Compatibility_Properties
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 3.
Ce qui sert justement à pouvoir en partie traiter un document Unicode avec des programmes ne supportant pas Unicode.
La commande
iconv
sert à faire de la transcription tandis qu'une bibliothèque Unicode permet de:Tu vois bien que
iconv
fait quand même beaucoup moins qu'une vraie bibliothèque Unicode.Dans mon commentaire, je dis que
awk
montre ses limites quand on a besoin de Unicode et tu réponds que ce n'est pas le cas parcequ'on a en pratique pas très souvent d'Unicode: c'est une réponse à côté de la plaque![^] # Re: Presque d'accord ...
Posté par Ignatz Ledebur . Évalué à -2.
Non, dans ma réponse, je dis plusieurs choses :
Plus généralement, le problème que tu pointes n'a encore ici que peu à voir avec Unicode, mais plus avec le support de l'encodage en général. On pourrait plutôt dire que dès que tu ne peux plus supposer que l'utilisateur traite des documents en accord avec son LC_CTYPE, le shell ne convient pas (même en Perl, ce n'est pas une partie de plaisir : extraire l'encodage du source, langinfo &cie pour obtenir le charset local, configuration des différents descripteurs… )
[^] # Re: Presque d'accord ...
Posté par Antoine . Évalué à 3.
Ben non, raté. Je cite le message auquel tu réponds :
« La commande iconv sert à faire de la transcription tandis qu'une bibliothèque Unicode permet de: [etc.] »
[^] # Re: Presque d'accord ...
Posté par Ignatz Ledebur . Évalué à 2. Dernière modification le 26 septembre 2014 à 10:43.
C'est vrai que dans le premier message auquel je réponds, Mickaël parle de problèmes au-delà de « l'extraction de pures données », ce qui anticipe l'essentiel de mes objections. Du coup on est bien d'accord qu'il faut plus qu'iconv et un AWK UTF-8 dans ces cas-là. Manque d'attention de ma part : Sorry for the noise, comme qu'on dit…
[^] # Re: Presque d'accord ...
Posté par pasBill pasGates . Évalué à -8.
Bonne idee, comme ca il pourra decouvrir PowerShell et se demander pourquoi ces hommes des cavernes s'acharnent a utiliser un outil prehistorique qui n'a aucune structure et qui est si facilement sujet a erreur.
[^] # Re: Presque d'accord ...
Posté par Michaël (site web personnel) . Évalué à 7.
Le
shell
est lent, vieux et pas simple d'accès. Il a cependant une qualité importante qui met à peu près tout le reste KO: en vertu de son grand âge:Pour ce qui est de la comparaison avec le PowerShell je me contenterai d'observer qu'il ne fonctionne pas sur les systèmes d'exploitation qui m'intéressent (FreeBSD, Mac OS X et Debian GNU/Linux). Mais pour ceux qui utilisent des systèmes Microsoft c'est sûrement un outil très utile si cela ressemble au shell. Ceci dit, on peut répondre aux gros trolls velus sans cracher sur ses propres parents!
[^] # Re: Presque d'accord ...
Posté par pasBill pasGates . Évalué à -2.
Il y a un port pour Mono en Alpha, toujours developpe : https://github.com/Pash-Project/Pash/
[^] # Re: Presque d'accord ...
Posté par BAud (site web personnel) . Évalué à 3.
ça ressemble plutôt à un mix entre les .BAT et le VBS, avec une logique objet et quelques commandes correctement documentées
malencontreusement, windows a peu d'héritage d'Unix :/ Hormis si tu installes un cygwin (mais dans ce cas, autant utiliser une distribution GNU/Linux…).
[^] # Re: Presque d'accord ...
Posté par Reihar . Évalué à 2.
Il m'arrive parfois de devoir utiliser Windows pour utiliser certains logiciels ou jeux. Crois moi, Cygwin change la vie.
[^] # Re: Presque d'accord ...
Posté par lolop (site web personnel) . Évalué à 3.
Je n'ai jamais compris pourquoi Microsoft a redéveloppé un nouveau langage de shell plutôt que s'orienter vers un Python ou Ruby, qui s'adaptent très bien à ce genre d'usage, et bénéficier ainsi de la portabilité et de tout l'écosystème qu'ils apportent.
(enfin, "jamais"… j'ai bien une idée du pourquoi)
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Presque d'accord ...
Posté par barmic . Évalué à 4.
L'intérêt de PowerShell est vraiment dans le runtime .Net, c'est ce qui permet de construire des bouts avec les différents langages de la plateforme .Net tout en gardant les concepts objets.
Mais j'ai l'impression que PowerShell a du mal à décoller. Les admin/dev windows ne sont pas très enclins à s'y mettre et je ne sais pas si les gros logiciels MS ont une API PowerShell intéressantes (est-il envisageable de manipuler word via PowerShell par exemple ?).
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Presque d'accord ...
Posté par lolop (site web personnel) . Évalué à 2.
J'ai lu qq part qu'il y avait des outils wrappers COM vers CLR, et le package pywin32 donne directement accès à COM, donc au CLR pour peu que les wrappers aient été créés. Et il semble y avoir d'autres façons. Je reste dubitatif sur l'intérêt d'avoir créé un nouveau langage.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Presque d'accord ...
Posté par SLC78 . Évalué à 1.
Ca dépend pour quoi on veut utiliser PowerShell. Perso, je l'utilise surtout pour gérer un peu et sortir directement des feuilles Excel de mon vCenter et de mes ESXi.
Y pas mal d'exemples là : http://www.hypervisor.fr/?page_id=3637
[^] # Re: Presque d'accord ...
Posté par pasBill pasGates . Évalué à 2.
Tu peux controler n'importe quel objet COM a travers PowerShell, et a peu pres tous les softs d'entreprise MS ont des cmdlet PowerShell specifiques, ainsi que de plus en plus de softs d'entreprise d'autres boites.
Maintenant, changer les habitudes des sysadmins, on sait tous que c'est pas simple…
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à -1.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: Presque d'accord ...
Posté par kna . Évalué à 0.
Il n'y a pas que les scripts dans la vie. Pour l'utilisation en ligne de commande intéractive, Powershell est plus adapté que Python ou Ruby (malgré ses commandes à rallonge).
[^] # Re: Presque d'accord ...
Posté par lolop (site web personnel) . Évalué à 3.
As-tu déjà essayé ipython ?
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 4.
Rien que le nom POWERShell me fait marrer …
cela fait penser aux personnes qui ont une GROSSE voiture style 4x4 pour compenser … quelque chose :)
(désolé j'ai pas pu résister, mais je sais j'aurais du attendre dredi)
[^] # Re: Presque d'accord ...
Posté par zurvan . Évalué à -1.
POWERshell, petit bit
« Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher
[^] # Re: Presque d'accord ...
Posté par zurvan . Évalué à 1.
et en toute logique…
« Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher
[^] # Re: Presque d'accord ...
Posté par steph1978 . Évalué à 4.
Justement non.
Les outils comme awk, join, sort et autres offrent un niveau d'abstraction supérieur et une plus grande spécialisation que python/perl/riby.
Il faut donc d'abord regarder si ils peuvent résoudre ton problème avant de passer à un outil plus généraliste.
Dans ta logique il faudrait tout faire en C/asm.
[^] # Re: Presque d'accord ...
Posté par Christophe B. (site web personnel) . Évalué à 3.
L'asm ya que ca de vrai :)
D'accord pour le "spécialisation", c'est vrai, mais bien souvent tu pars d'un bout de code pour résoudre ton problème, ensuite tu le mets dans un cron (par exemple) et donc tu as besoin de log, puis d'historiser les logs, ensuite on te demandes un petite modif, puis une autre etc …
Et je ne parle pas d'ergonomie pour l'utilisateur final :)
Bref le coté spécialisation c'est bien, mais au bout de quelques temps tu va vers le coté généraliste.
Quand tu as un bon marteau, tout les problèmes ressemblent à des clous :)
Mais tu as tout a fait raison que si awk join paste (et lam que je connaissais pas :) ) sont toujours la c'est pas pour rien. et pour longtemps :)
(pas comme le power shell ;-) … (ah zut on est que mardi) )
[^] # Re: Presque d'accord ...
Posté par barmic . Évalué à 2.
Une commande
logger
et tu gère tes logs via syslog (ou le deamon de Lennart) comme un pro (avec rotation etc).C'est toujours subtile de savoir quel est le meilleur outil pour une tâche donnée, mais il faut pas croire que le shell est fait pour des scripts jetables. Le fait d'être à un très haut niveau d'abstraction permet de faire énormément de choses de manière très simple/efficace.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Presque d'accord ...
Posté par lasher . Évalué à 2.
Ce qui manque à Perl selon moi, c'est la possibilité d'utiliser les pipes à l'intérieur d'un programme Perl (un peu comme
|>
qui existent OCaml comme l'a expliqué Michaël, mais aussi Scala et le cousin d'OCaml, F#). Mais à part ça, je ne vois pas en quoi le shell est tellement plus abstrait que Perl/Python/Blah, surtout si le langage a une REPL.En Perl, par exemple, je peux faire un truc du genre
alias perlstd='perl -ne'
pour avoir un interpréteur Perl en ligne de commande (mais il sera très fragile, assurément). Ça me permettra d'écrire ce genre de choses:Donc évidemment, s'il existe des commandes pour faire la même chose, qui en plus ne nécessiteront pas de créer une instance d'interpréteur perl, mieux vaut les utiliser (et en plus les noms seront plus cours, même si je pourrais faire les alias qui vont bien pour pallier ce genre de problème).
Par contre, avec ce même alias
perlstd
, je peux aussi faire tout ce que proposent sed, awk, grep, ce qui par définition indique que Perl est plus abstrait que ces outils. Et plus général aussi, bien sûr. Bref, ceci est de la sodomie de diptères pour dire que je ne suis pas d'accord pour dire que le shell est plus abstrait. Au contraire, le shell est moins abstrait, et c'est ce qui fait sa force.[^] # Re: Presque d'accord ...
Posté par anaseto . Évalué à 3. Dernière modification le 24 septembre 2014 à 21:47.
En Perl tu ne peux pas faire une pipe qui permette de paralléliser des choses (en OCaml non plus d'ailleurs, pour le moment, je crois), mais tu peux écrire facilement une fonction
pipes
qui prend en argument une valeur, puis une liste de fonctions, et renvoie la valeur composée de ces fonctions.Et le
|>
d'OCaml c'est juste (en plus performant)let (|>) x f = f x
, c'est juste du sucre syntaxique pour la composition en utilisant le parenthésage de priorité par défaut pour les opérateurs. Bref, n'importe quel langage qui permet de passer des fonctions en argument à d'autres fonctions permet de faire la même chose.[^] # Re: Presque d'accord ...
Posté par lasher . Évalué à 2.
L'avantage du
|>
c'est que c'est lisible et donne naturellement l'ordre des opérations. Quelque part, le fait qu'il y ait une écriture de typefonction op fonction op fonction ... op ...
me permet de visuelle situer ce qui se passe, alors qu'avec ta solution (qui fonctionne, pas de souci là-dessus), il faut que mon cerveau réfléchisse un chouïa plus.Concernant le parallélisme : en OCaml je ne sais pas si les pipes le permettent, mais j'avais cru comprendre qu'en F# c'était faisable.
[^] # Re: Presque d'accord ...
Posté par barmic . Évalué à 3.
Utiliser perl
-ne
ou-la
n'a pas grand chose avoir avec l'utilisation de perl en remplacement de script shell. Ils permet de créer facilement des filtres qui utilisent des comportements proches de grep, sed ou awk. Ils sont vraiment très bien et je m'en sert régulièrement (l'exemple ne marche pas je n'avais pas pu tester).Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Presque d'accord ...
Posté par lasher . Évalué à 1.
Disons que c'est peut-être ma méconnaissance de sh/bash (zsh je ne connais vraiment pas), mais un script qui fait plus de 20 lignes en (ba)sh, ça me pique les yeux, même si c'est moi qui l'écris. Dès que j'ai besoin d'écrire des fonctions, j'ai tendance à très vite aller voir du côté de Perl. Ça a aussi sans doute à voir avec le fait que si je ne peux pas simplement chaîner des commandes et que j'ai besoin d'ajouter de la logique, s'il ne s'agit pas de boucles très simples où tout est visible depuis celle-ci, je trouve le shell trop peu expressif (bon c'est pas exactement comme ça que je le pense1, mais j'ai le cerveau embrumé ce matin…).
En fait je suppose que dès qu'on parle de manipulation « fine » de chaînes de caractères, j'ai tout de suite tendance à penser à un langage plus expressif (et avec plus de modules déjà écrits pour moi) que le shell.
J'ai écrit tout plein de scripts bash qui appelaient d'autres scripts (Perl ou bash) pour traiter des logs, générer de jolis graphiques, et m'envoyer un mail quand le traitement était fini. ↩
[^] # Re: Presque d'accord ...
Posté par barmic . Évalué à 4.
L'intérêt du shell c'est :
Le parallélisme en perl c'est mort bien souvent et utiliser POE c'est euh… comme chercher à détruire l'univers pour tuer une mouche. La gestion des fichier, je crois qu'il y a un module pour avoir comme les globings, mais c'est peu utilisé je sais pas si c'est dans les distrib' de base. La manipulation de programme est pas trop mal avec la possibilité d'ouvrir de lancer des programme comme on ouvre des fichiers.
Comprends bien j'aime perl (vraiment), mais ce que je fais avec perl et ce que je fais en shell forment 2 ensembles totalement disjoints.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Presque d'accord ...
Posté par lasher . Évalué à 3.
Je ne comprends pas bien pour le globbing. J'utilise fréquemment ce genre de code (simplifié avec
say
pour l'exemple) :Certes, il faut rajouter les < et >, mais ça s'arrête globalement là. N'importe quel bouquin qui enseigne le Perl correctement (je pense entre autres aux bouquins de chez O'Reilly) expliquent comment utiliser le globbing.
[^] # Re: Presque d'accord ...
Posté par Antoine . Évalué à 2.
J'ajouterais un quatrième point : des implémentations simples et sécurisées.
# $(...) et /bin/sh
Posté par cracky . Évalué à 10. Dernière modification le 22 septembre 2014 à 12:47.
L'entreprise pour laquelle je travaille traîne de vieux Solaris 8 (SunOS 5.8).
Sur ces systèmes le /bin/sh n'accepte pas les $(…) l'utilisation des backquotes est obligatoire.
Par contre, je n'ai pas fouillé les faux plafonds.
Cette syntaxe $(…) ne fait pas pour moi partie de la syntaxe sh "originelle".
[^] # Re: $(...) et /bin/sh
Posté par Michaël (site web personnel) . Évalué à 10.
C'est exact mais la syntaxe
$(…)
fait partie de POSIX depuis un bon moment maintenant — bien-sûr quand on fait de l'archéologie, on est dans un cas particulier![^] # Re: $(...) et /bin/sh
Posté par grim7reaper . Évalué à 1. Dernière modification le 22 septembre 2014 à 13:36.
Poste supprimé (j'ai oublié de rafraîchir avant de poster, ce que je voulais écrire a déjà été écrit)
# Paramètres d'xargs
Posté par Cyril Brulebois (site web personnel) . Évalué à 5.
Prendre quelques minutes pour consulter la page de manuel d'xargs est probablement un bon investissement.
Une option ultra classique (avec -0/--null, déjà mentionnée) est -r/--no-run-if-empty, qui permet typiquement d'éviter de lancer une commande sans paramètre, ce qui peut éviter un code de retour en erreur et un script/crontab/etc. qui termine un peu trop vite parce que « set -e » avait été déclaré.
Debian Consultant @ DEBAMAX
[^] # Re: Paramètres d'xargs
Posté par Le Gab . Évalué à 7.
Sauf que je la trouve imbitable, comme celle de sed. Les manpage de tels programmes auraient gagné à etre plus concis et un peu plus étoffés en exemples.
Les manpage GNU, c'est d'une complexité effarante.
[^] # Re: Paramètres d'xargs
Posté par SChauveau . Évalué à 2.
La manpage de xargs est trop complexe? A la rigueur, je peux comprendre pour celle de bash mais celle de xargs me semble claire et concise. Une page de man n'est pas un tutoriel. Elle donne une courte description de la commande et de ses arguments avec quelques exemples.
# Portabilité
Posté par barmic . Évalué à 8.
La gestion de la portabilité est un sujet assez épineux pour du shell. On parle souvent de se contenter de POSIX, il arrive que ce soit assez contraignant pour un intérêt limité.
Lorsque le code est distribué à l'ensemble de la planète, c'est normal de chercher la plus grande portabilité possible (et donc de choisir POSIX), mais dans bien d'autres cas ce n'est pas aussi clair :
Une autre approche de la portabilité peut être d'utiliser le moins de programmes possible. On peut par exemple créer un script zsh qui n'utilisera jamais le moindre outil GNU. Ça peut simplifier les dépendances (on ne dépend plus que de zsh) tout en ayant des fonctionnalités plus pratiques performantes.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# ls et globbing
Posté par sebre . Évalué à 5.
C'est moyen, comme "règle d'or".
Cette boucle dans un répertoire vide va te renvoyer '*' comme nom de fichier. De même si le masque du globbing n'a aucune correspondance, c'est le masque lui même qui est renvoyé. Ce qui oblige à tester la nature du retour. La forme $(ls * 2>/dev/null) par contre est moche, mais pas piégeuse.
[^] # Re: ls et globbing
Posté par SChauveau . Évalué à 4.
Le problème du masque étendu en lui même quand rien ne 'match' peut se résoudre facilement avec l'option
Cela marche dans Bash. Pour les autres shells c'est à vérifier. Il y a aussi l'option 'dotglob' qui permet de ne pas ignorer les fichiers cachés (donc commençant par un '.')
Il m'est aussi arrivé de tomber sur des scripts utilisant 'ls' pour obtenir des informations sur les fichiers. C'est assez risqué car il existe de nombreuses variantes de 'ls' et le résultat peut aussi dépendre de la locale.
Une meilleure solution est d'utiliser 'stat'
[^] # Re: ls et globbing
Posté par Ignatz Ledebur . Évalué à 3.
Je suis d'ailleurs surpris de ne rien lire au sujet de la locale dans ce journal des bonnes pratiques. C'est en effet généralement une bonne idée de toujours commencer par positionner LC_ALL (qui. rappelons-le, ne devrait jamais être définie dans l'environnement courant) à "C", afin que les commandes aient des sorties formatées conformément à POSIX (en plus de gagner en performances pour les commandes où l'ajout d'utf-8 s'est fait avec un certains coût), quitte ensuite à l'enlever à certains points précis (avant mailx, par exemple, qui dans sa version Heirloom échouera à envoyer le message si son encodage n'est pas en accord avec la locale).
Dans le même genre, on peut aussi mettre systématiquement le masque à 022, afin d'éviter les mauvaises surprises si le script doit créer des dossiers/fichiers.
[^] # Re: ls et globbing
Posté par Michaël (site web personnel) . Évalué à 4.
La règles d'or c'est que:
ls
on peut utiliser le globbing oufind
— pas sans discernement, sans que tu le soulignes.Elles est beaucoup plus piégeuse que le globbing ou l'utilisation de
find
, précisément pour les raisons évoquées ci-dessus.# Lire les recommandations POSIX!
Posté par Jiehong (site web personnel) . Évalué à 7.
On parle souvent de POSIX, alors en lire le contenu est une bonne chose !
On y apprend, par exemple, qu'il est préférable d'utiliser
printf
au lieu d'echo
…[^] # Re: Lire les recommandations POSIX!
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 5.
Et qu'il est conseillé d'utiliser plusieurs
test
joints par des&&
ou||
plutôt qu'un seultest
avec ses opérandes intégrées-a
et-o
, celles-ci étant vouées à la caducité à plus ou moins court terme.[^] # Re: Lire les recommandations POSIX!
Posté par Tonton Th (Mastodon) . Évalué à 3.
Pourrait-on avoir plus d'info sur ce sujet ?
[^] # Re: Lire les recommandations POSIX!
Posté par Michaël (site web personnel) . Évalué à 3.
Une remarque connexe plutôt qu'une vraie réponse: POSIX n'exige de la commande
test
que de travailler avec un nombre réduit d'arguments (genre 5 ou 6, je ne sais plus) ce qui rend en pratique l'emploi des opérateurs-a
et-o
impossible si on refuse de sortir du cadre POSIX.[^] # Re: Lire les recommandations POSIX!
Posté par tyoup . Évalué à 1.
en gros jamais, mais bon, dans le doute…
[^] # Re: Lire les recommandations POSIX!
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 3.
Le mieux est encore d'aller voir la norme POSIX en question, mais en gros, c'est une extension X/Open, qui est parfois mise en œuvre de façon ambigüe, et qui est dangereuse à utiliser dans certains cas particuliers.
[^] # Re: Lire les recommandations POSIX!
Posté par Michaël (site web personnel) . Évalué à 3.
C'est pas comme si la dépêche racontait n'importe quoi! :-)
# Gestion des dates
Posté par barmic . Évalué à 10.
Les dates sont une plaie en informatique. C'est vraiment très compliqué à gérer (entre les mois de 30 à 31 jours, sauf un qui fait 28 jours sauf tout les 4 ans, les secondes intercalaires qui peuvent être ajoutées ou supprimée de temps en temps, le changement d'heure…) et on trouve régulièrement des bug dans des logiciels pourtant éprouvés (la libc par exemple).
Mon conseil, ne gérer pas les dates vous même (en shell comme ailleurs). Laissez-ça à des API qui font ça très bien. En shell cette API c'est
date
(c'est un standard POSIX utilisable avec n'importe quel shell).Son usage est assez simple (mais ça ne dispense pas de lire le man), l'idée c'est de convertir toutes les dates en entier (le nombre de secondes depuis epoch) puis de comparer ces entiers entre eux, puis de les convertir dans le format que l'on souhaite.
Par exemple si je souhaite dans mon script savoir si nous sommes après ou avant le 6 octobre 2014 je vais faire ça ainsi :
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Gestion des dates
Posté par Renault (site web personnel) . Évalué à 3.
Note que normalement date ne gère pas les secondes intercalaires, car ce n'est pas répercuté dans le timestamp.
[^] # Re: Gestion des dates
Posté par barmic . Évalué à 3.
Oui l'exemple de la libc n'est peut être pas le meilleur, mais si déjà t'évite les bugs classiques comme les mois de 28 à 31 jours par exemple c'est déjà pas mal.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Gestion des dates
Posté par Jiehong (site web personnel) . Évalué à 5.
Je teste les maths plutôt comme ça :
[^] # Re: Gestion des dates
Posté par Maxime (site web personnel) . Évalué à 1. Dernière modification le 22 septembre 2014 à 19:26.
Tu peux tester avec les double brackets :
[^] # Re: Gestion des dates
Posté par Michaël (site web personnel) . Évalué à 2.
C'est obsolète et déconseillé, la forme recommandée est d'utiliser
$((…))
.[^] # Re: Gestion des dates
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 4.
Ce n'est pas obsolète, mais c'est du pur Bash, pas portable.
[^] # Re: Gestion des dates
Posté par Michaël (site web personnel) . Évalué à 2.
Mea culpa, j'ai cru lire
$[…]
.[^] # Re: Gestion des dates
Posté par Dolmen (site web personnel) . Évalué à 2.
Encore mieux :
Mainteneur de LiquidPrompt - https://github.com/nojhan/liquidprompt
[^] # Re: Gestion des dates
Posté par sebre . Évalué à 2.
Exactement. Et autant éviter de gérer les changements d'heure été/hiver à la main.
[^] # Re: Gestion des dates
Posté par flan (site web personnel) . Évalué à 2.
Mais est-ce que ce sont des heures UTC ou des heures locales ?
Perso, je fais tous mes scripts en Python dès qu'il y a des dates (j'ai alors des objets datetime qui ont un fuseau horaire) ou des caractères bizarres (j'ai alors des objets qui gère proprement l'Unicode). Mais bon, ça reste toujours galère de gérer les fichiers avec des accents sous Linux, ne serait-ce parce qu'on peut avoir n (avec n grand) fichiers différents ayant tous le même nom unicode.
[^] # Re: Gestion des dates
Posté par barmic . Évalué à 5.
Locale pour UTC, il faut l'indiquer explicitement. Tu peut aller voir
info date
pour tous les détails.Ça tombe bien la commande date gère les fuseaux horaires.
Pour de gros besoin de date oui le shell n'est pas une bonne idée, de même pour les mathématiques, pour des choses simples, il n'y a pas de raison de tout réécrire pour si peu.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Gestion des dates
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 5.
Hein, comment ça ? Deux fichiers ne peuvent pas avoir le même nom sur un même système de fichiers non…
[^] # Re: Gestion des dates
Posté par dtrystram . Évalué à 1.
ce n'est pas plutôt mois/jour/année le format et donc le 10 juin 2014 plutôt ?
[^] # Re: Gestion des dates
Posté par barmic . Évalué à 3.
En effet j'ai écris l'exemple un peu vite. Ça montre que ça reste casse gueule.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# NULL dans IFS?
Posté par SChauveau . Évalué à 1.
Je suis assez surpris par l'exemple consistant à mettre le caractère NUL (\000) dans IFS.
Autant que je sache, cela ne marche pas dans Bash qui ne peut pas manipuler NUL dans les variables.
Il semble que cela fonctionne dans d'autres shells comme ZSH.
Pour Bash, la solution réside dans l'option -d de 'read'
find . -print0 | while read -d $'\0' file ; do echo == $file ; done
La syntaxe $'…' active l'interprétation des séquences d'échappements dans la chaine …
C'est équivalent à $(printf "…")
# un ptit mot sur dash
Posté par Julien Wajsberg . Évalué à 4.
Merci pour l'article, j'ai notamment appris que $(..) et printf étaient maintenant dans POSIX :)
Je voulais noter que si vous avez besoin de doc sur le shell, la page man de dash est vraiment bien foutue.
# shellcheck
Posté par lecteur . Évalué à 2.
Le tout premier lien dirige vers S_h_ellCheck, et non pas vers S_p_ellCheck, comme indiqué. Si quelqu'un pouvait corriger.
[^] # Re: shellcheck
Posté par Benoît Sibaud (site web personnel) . Évalué à 3.
Corrigé, merci.
# Advanced Bash-Scripting Guide
Posté par albatar . Évalué à 6.
Je suis étonné que personne ait donné les liens vers abs :
http://www.tldp.org/LDP/abs/html/
et en fr :
http://abs.traduc.org/abs-fr/
# une discussion intéressante
Posté par Axel . Évalué à 1.
https://news.ycombinator.com/item?id=8054440
# passionnant post
Posté par plieuse . Évalué à 2.
Merci pour ce post très intéressant, j'ai appris plein de choses.
# Et le set ?
Posté par Sébastien Koechlin . Évalué à 8.
Le shell est très permissif avec les variables, et je demande toujours que les scripts soient développés avec:
set -u: Write a message to standard error when attempting to expand a variable that is not set, and if the shell is not interactive, exit immediately.
set -e: If not interactive, exit immediately if any untested command fails. The exit status of a command is considered to be explicitly tested if the command is used to control an if, elif, while, or until; or if the command is the left hand operand of an “&&” or “||” operator.
C'est pénible au début; mais on évite pas mal de bugs bien compliqués, parce que lorsqu'on a un soucis et que le script continue a exécuter 20 lignes de codes derrière avec des mauvaises valeurs; on peut faire de beaux feux d'artifices.
[^] # Re: Et le set ?
Posté par xcomcmdr . Évalué à 2.
C'est triste ton avis sur les feux d'artifices. :'(
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Et le set ?
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 6.
Pour info,
set -e
est la norme pour les scripts liés à l'empaquetage Debian (genre le postinst d'un paquet).À noter que la solution de mettre
#! /bin/sh -e
en tête de fichier n'est pas équivalente, parce qu'elle n'applique cette option qu'aux scripts lancés directement en./script
et non à ceux qu'on lancerait explicitement via un shell ensh script
.# Wiki ?
Posté par mrr . Évalué à 1.
Ça vaudrait peut-être le coup de transformer cette dépêche en page Wiki, non ?
Envoyé depuis ma Debian avec Firefox
# typo
Posté par fusible . Évalué à 1.
Il me semble qu'il manque une quote dans la section sur l'Analyse de la sortie de la commande ls :
NUL=$(printf '\000)
Super dépêche et les commentaires ne sont pas en reste !
[^] # Re: typo
Posté par Benoît Sibaud (site web personnel) . Évalué à 6.
Corrigé, merci. Ça aurait été dommage que les gens utilisant le shell aient un choc…
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.