OVH Cloud OVH Cloud

recuperer les variables d'un nom de fichier

17 réponses
Avatar
sleepee
je suis debutant (je decouvre le shell)

j'ai besoin de recuperer les variables a partir d'un nom de fichier

TOTO_<ChannelCode>_<CampaignCode>_<Wave>_YYYY-MM-DD_HHMMSS.dat

(par example TOTO_SMS_CAMPAIGNSYSTEM_12_2004-12-07_120000.dat)

$Channelcode
$CampaignCode
$Wave
$Date

merci

7 réponses

1 2
Avatar
drkm
Stephane Chazelas writes:

set x $fic; shift


Quelle est la différence avec :

set $fic

?

--drkm

Avatar
Nicolas George
drkm wrote in message :
set x $fic; shift


Quelle est la différence avec :

set $fic


Ce qui se passe si $fic commence par un -. Sans le x, ce sera considéré
comme une option. À noter que la méthode propre (et standard, mais peut-être
pas totalement portable :( ) de faire ça serait

set -- $fic


Avatar
Greg
2004-12-09, 23:39(+01), Greg:
[...]

fic=TOTO_SMS_CAMPAIGNSYSTEM_12_2004-12-07_120000.dat
Channelcode=`echo $fic | cut -d'_' -f2`
CampaignCode=`echo $fic | cut -d'_' -f3`
Wave=`echo $fic | cut -d'_' -f4`
Date=`echo $fic | cut -d'_' -f5`




[...]

IFS=_
set -f
set x $fic; shift
Channelcode=$2
CampaignCode=$3
Wave=$4
Date=$5



[...]

Je ne pense pas que mon script mette à plat un PC (même mon vieux 166MX) !




Alors, essaie avec:

fic='/*/*/*/../../../*/*/*/../../../*/*/*/../../../whatever'

Si c'est un Linux, ca peut meme peut-etre crasher ta machine.
La, le probleme n'est pas dans le script, mais dans le chemin ;-) !

Plus sérieusement, j'utilise, dans la cadre de mon boulot, ce genre de
script très facile et rapide à faire.
le "fic" vient généralement du résultat d'un find et il m'arrive de
traiter des centaines de fichiers dans des boucles (avec des
arborescence conséquente). Je n'ai JAMAIS eu de crash machine (il est
vrai aussi que c'est une machine de calcul relativement récente).


Par contre, le tiens m'interesse:
- en quoi est il plus générique que celui que celui que je propose (tu
définis le même séparateur que moi et tu prends les mêmes champs que moi )?



Non, le tiens definit plusieurs separateur (NL le separateur
implicite de ligne de cut et _) et ton code, comme je l'ai deja
dit, va foirer (avec des resultats differents selon le shell
et le systeme) si fic contient des blancs (space, tab, newline),
des wildcards ou des backslashs.

OK, mais :

NL = New Line ?
Si oui, peut on avoir NL dans le nom d'un fichier sous Unix/linux ?
Jamais vu !
Pour le space et tab, j'ai jamais rencontré de problèmes (peut être par
chance): ils ne sont pas compté comme délimiteurs. (J'utilise linux
FEDORA Core2 sur mon PC perso et REDHAT Ent. au boulot)
J'utilisait aussi ce genre de script sous HP-UX (avant qu'on bascule
sous Linux)


- je ne connais pas bien l'instuction set (je sais juste qu'elle agit
sur l'environnement bash)



Elle permet de positionner les "positional parameters" ($1,
$2...)

set a b
fait en sorte que $1 contiennent "a" et $2 contiennent "b" et $#
contienne 2.


mais son utilisation ne peut elle pas poser
de problèmes



On perd les arguments initiaux du script, mais en principe on
les aura stockés au prealable dans des variables plus parlantes.
$@ etant le seul array de "sh", on utilise ce mechanisme assez
frequemment.


(tu suggères de modifier le séparateur de champ IFS !)



Oui ! Chaque fois que tu utilises une variable non-quotee, il
faut fixer la valeur d'IFS au separateur que l'on veut et
activer/desactiver la filename generation suivant qu'on veuille
ou non que les /wildcards/ soient expanded (set -f), (ce que tu
n'as pas fait), c'est pourquoi il ne faut quasi jamais laisser
une variable non-quotee (mon code etant un exemple des rares cas
ou ca peut etre utile).

Que veux tu dire par "variable non quotee" et par "expanded"



- si tu as des billes (site internet notamment) sur l'optimisation des
scripts, je suis preneur ..


[...]

www.shelldorado.com a des exemples pas trop mal faits.

J'ai commencé à regarder le site : il a l'air pas mal.

Merci.


Dans les grande lignes, je suis qd meme assez d'accord avec toi. Tu
cherches a optimiser un maximimun les scripts que tu fais et c'est très
bien.
Par contre, va expliquer à l'utilisateur Linux "de base" (n'oublions pas
le sujet initial du Post !) qu'il a 'Forké' son process 11 fois ....
En gros, je suis convaincu que mon script est basique et "rustique",
mais il marche !
Le tiens marche aussi mais il est beaucoup plus évolué et réfléchi : il
est plutot destiné à qqu'un qui connait bien le fonctionnement des syst.
unix/linux.
Autre remarque : n'oublions pas qu'on parle d'un language interprété (on
fait quand même mieux en terme d'optimisation !).


Bonne Soirée

Greg




Avatar
Stephane Chazelas
2004-12-10, 22:03(+00), Nicolas George:
drkm wrote in message :
set x $fic; shift


Quelle est la différence avec :

set $fic


Ce qui se passe si $fic commence par un -. Sans le x, ce sera considéré
comme une option. À noter que la méthode propre (et standard, mais peut-être
pas totalement portable :( ) de faire ça serait

set -- $fic


Pas avec le Bourne shell.

Avec le Bourne shell,

set --

ne fait rien (il ne remet pas la liste des positional parameters
a zero).

shift "$#"
set -- $fic

ou

set x $fic
shift

sont portables (a noter que le mechanisme de word splitting est
different d'un shell a l'autre, meme pretendument POSIX
conformant).

--
Stephane



Avatar
Stephane Chazelas
2004-12-10, 23:04(+01), Greg:
[...]
fic='/*/*/*/../../../*/*/*/../../../*/*/*/../../../whatever'

Si c'est un Linux, ca peut meme peut-etre crasher ta machine.
La, le probleme n'est pas dans le script, mais dans le chemin ;-) !

Plus sérieusement, j'utilise, dans la cadre de mon boulot, ce genre de
script très facile et rapide à faire.
le "fic" vient généralement du résultat d'un find et il m'arrive de
traiter des centaines de fichiers dans des boucles (avec des
arborescence conséquente). Je n'ai JAMAIS eu de crash machine (il est
vrai aussi que c'est une machine de calcul relativement récente).


Rien n'empeche un petit malin de faire

mkdir -p '/tmp/*/*/*/*/*'
touch -t 200001010000 '/tmp/*/*/*/*/*/*'
ln -s / '/tmp/*/foo'

Un:

old=`find /tmp -mtime +60 -print`

va te renvoyer /tmp/*/*/*/*/*/*

un echo $old var etre plus lent que prevu.

Mais, mon argument n'etait pas tant le risque potentiel que le
fait qu'utiliser une variable non quotee n'est pas correct a
cause de la signification particuliere des quotes en shell qui
est differente (voire quasi a l'opposé) de celle qu'elles ont
dans les autres langages.

[...]
OK, mais :
NL = New Line ?
Si oui, peut on avoir NL dans le nom d'un fichier sous Unix/linux ?
Jamais vu !


Bien sur, pourquoi pas. Les seuls caracteres interdits sont NUL
et /.

On peut faire des trucs marants comme:

touch $'e[2t'

Fait un ls | cat ou find . dans un xterm apres.

Pour le space et tab, j'ai jamais rencontré de problèmes (peut être par
chance): ils ne sont pas compté comme délimiteurs. (J'utilise linux
FEDORA Core2 sur mon PC perso et REDHAT Ent. au boulot)
J'utilisait aussi ce genre de script sous HP-UX (avant qu'on bascule
sous Linux)


a="A B"
echo $a

renvoie "A B". C'est un coup de chance, le shell decoupe ca en
deux arguments mais heureusement, echo les recolle en mettant
une... espace entre.

avec a="A B", a="A B" (tab), evidemment, ca ne marche plus.

[...]
Oui ! Chaque fois que tu utilises une variable non-quotee, il
faut fixer la valeur d'IFS au separateur que l'on veut et
activer/desactiver la filename generation suivant qu'on veuille
ou non que les /wildcards/ soient expanded (set -f), (ce que tu
n'as pas fait), c'est pourquoi il ne faut quasi jamais laisser
une variable non-quotee (mon code etant un exemple des rares cas
ou ca peut etre utile).

Que veux tu dire par "variable non quotee" et par "expanded"



Les double-quotes, en shell sont faits pour mettre des trucs
variables qui doivent etre considerees comme des "chaines de
characteres".

printf '<%s>n' "$var"

si $var doit etre consideree comme une chaine de caracteres.

printf '<%s>n' $var

si $var doit etre consideree comme une liste de patterns de
fichiers.

"expanded" par rapport a la "filename generation" ou "globbing"
or "filename expansion".

liste_de_patterns='/bin/* /etc/*'
chaine_de_caracacteres='*** text ***'
printf '<%s>n' $liste_de_patterns
printf '<%s>n' "$chaine_de_caracacteres"

Maintenant, essaie d'inverser:

printf '<%s>n' "$liste_de_patterns"
printf '<%s>n' $chaine_de_caracacteres

[...]
Dans les grande lignes, je suis qd meme assez d'accord avec toi. Tu
cherches a optimiser un maximimun les scripts que tu fais et c'est très
bien.
Par contre, va expliquer à l'utilisateur Linux "de base" (n'oublions pas
le sujet initial du Post !) qu'il a 'Forké' son process 11 fois ....
En gros, je suis convaincu que mon script est basique et "rustique",
mais il marche !


Il marche dans le cas general mais est un nid de bugs.

Le probleme de performance est secondaire. Si on veut des
performances, on n'ecrit pas de scripts shells.

Je mettait l'accent sur les problemes lies a des mauvaises
pratiques de programmation (oublier les quotes autour des
variables, utiliser echo).

--
Stephane


Avatar
Nicolas George
Stephane Chazelas wrote in message
:
Avec le Bourne shell,

set --

ne fait rien (il ne remet pas la liste des positional parameters
a zero).


J'ai la Single Unix sous les yeux, et je peux dire : il devrait. Je viens
d'essayer avec tous les shells que j'ai sous la main (ce qui n'est pas tant
que ça, hélas : bash, zsh, dash, /bin/ksh de Solaris 9 et /usr/xpg4/bin/sh
de Solaris 9 se comportent bien. Seul /bin/sh de Solaris se comporte mal,
mais ce n'est pas nouveau, il ne connaît même pas ${foo#bar}.

Avatar
Stephane Chazelas
2004-12-11, 13:34(+00), Nicolas George:
Stephane Chazelas wrote in message
:
Avec le Bourne shell,

set --

ne fait rien (il ne remet pas la liste des positional parameters
a zero).


J'ai la Single Unix sous les yeux, et je peux dire : il devrait. Je viens
d'essayer avec tous les shells que j'ai sous la main (ce qui n'est pas tant
que ça, hélas : bash, zsh, dash, /bin/ksh de Solaris 9 et /usr/xpg4/bin/sh
de Solaris 9 se comportent bien. Seul /bin/sh de Solaris se comporte mal,
mais ce n'est pas nouveau, il ne connaît même pas ${foo#bar}.


Je parlais du Bourne shell, pas des shells POSIX. Le Bourne
shell n'est pas POSIX conformant.

Le /bin/sh de Solaris est un des derniers Bourne shells encore
vivants.

--
Stephane


1 2