Jump to content

Archived

This topic is now archived and is closed to further replies.

theocrite

[GLOBAL] 100% question pour un pinguin

Recommended Posts

Oué, moi non plus ! J'adore ce topic :)

Sinon, dommage qu'on puisse pas le piper dans un correcteur grammatical après, parce qu'à l'impératif il n'y a pas de "s" à "arrête".... ;o)

Share this post


Link to post
Share on other sites

:francais: J'y avait pensé aussi pour le 's' :transpi:

Je ne sais pas pourquoi, je m'attendais à ce que Sandeman nous sorte une commande magique.

Pareil que gauret et yoda, content de découvrir ça :mad2:

Share this post


Link to post
Share on other sites
et les autres options de paste sont faciles à implémenter... ils ont fait quoi quand ils ont programmé? :chinois:
En vrac :

Le paste gère les caractères échapés, possède une gestion des erreurs (dans les fichiers lu et erreurs d'écriture), prend un nombre quelquoque de fichiers en arguments, permet de choisir un séparateur, permet de procéder en série au lieu de procéder en parallèle (rotation 90°).

Pour la gestion des erreurs, il y a (entre autres)

xputchar (char c)
{ 
 if (putchar (c) < 0)
write_error ();
}

Il fait un test en plus sur chaque caractère en output, donc forcément ça doit prendre un peu plus de temps.

Share this post


Link to post
Share on other sites

Allez, une nouvelle questions pour nos acharnés, extraite d'une histoire vraie.

Mr G. (dont nous garderons l'anonymat) est en train de déployer Cacti sur un parc de serveurs FreeBSD. Pour cela, il faut installer SNMP sur ces serveurs. Les serveurs FreeBSD sont parfois un peu vieux, en version 4, mais l'arbre des ports a été régulièrement mis à jour pour disposer des dernieres versions des logiciels portés.

Jusque là, tout va bien.

Soudain, en faisant un "make install clean" dans /usr/ports/net-mgmt/net-snmp sur un vieux serveur FreeBSD 4.11, Mr G. constate une erreur de compilation ! C'est un patch qui s'est mal appliqué, et qui échoue avec l'erreur : "sed : option -i inconnue".

Damn ! Le sed du système, donc de FreeBSD 4.11, ne gère pas encore l'option -i, et le Makefile des ports en a besoin parce que les ports sont à jour.

Qu'à cela ne tienne, nous allons écrire un petit wrapper. Mais attention, le wrapper doit être compatible à 100% avec sed, et accepter la syntaxe d'appel de l'option -i (ex : sed -i.bak -e 's/truc/machin bidule/g' /chemin/vers/fichier) pour pouvoir être un remplaçant parfait !

Ah oui, et pour rigoler : vous me ferez ça en bash :byebye:

Calculatrices non autorisées (sauf si elles tournent sous un OS libre)

Petite astuce, qui peut vous être utile ou pas : sous FreeBSD, les options des commandes sont forcément avant les arguments. Tout est un argument à partir du premier argument trouvé. Ex :

ls -l /usr : OK

ls /usr -l : Pas OK (ça cherche à faire un ls de /usr et de "-l")

Share this post


Link to post
Share on other sites

pas testé en profondeur (juste avec des echo :transpi: )

#!/bin/bash
SED=/usr/bin/sed

option=0
argv=""

for i in $*; do
	file=$i
	if [ $i = -i ]; then
			option=1
	else
			argv="${argv} $i"
	fi
done
if [ ${option} = 0 ]; then
	${SED} ${argv}
else
	${SED} ${argv} > /tmp/${file}
	mv /tmp/${file} ${file}
fi

Pas très joli joli d'ailleurs

bug connu :

- nom du fichier = -i (moui, enfin, bon, voila...)

- sed de l'entrée standart avec -i comme option comportement différent du sed avec -i (qui répond "sed: impossible de lire -: Aucun fichier ou rértoire de ce type" )

- et bien sur les problèmes avec tmp et mv (si le fichier /tmp/${file} existe et pas écrasable, mauvais , et si le fichier "seddé" n'est pas écrasable, création d'un fichier temporaire indésiré dans /tmp)

Share this post


Link to post
Share on other sites

Bon c'est quand même un script conséquent...

J'explique d'abord :

sed comporte de nombreuses options qui ne sont pas des fichiers (notamment les scripts avec "-e", mais aussi quelques opotions...)

Donc il faut trier tout ça et mettre de côté le nom des fichiers...

Ensuite pour faire le backup quand on met -i sans extension, c'est pas trop dur (avec le numéro du processus...)

Il faut gérer les fichiers avec espaces, et ça par contre c'est super chiant à faire...

Donc là ça marche même avec des fichiers genre "-i" (et même des fichiers n'importe où tant qu'à faire)

 $ ./sedwrap intrus -e 's/foo/bar/' -i.truc -- -i fichier\ avec\ des\ espaces

Bon donc voilà la bête :

http://rafb.net/paste/results/qd6Orz16.html

#!/bin/bash

SED=sed

args=""
inplace="no"
declare -a files

#gestion des arguments : récupération des fichiers et de l'option "-i"
while [ "$1" ]
do
case "$1" in
	--help|--version)	 $SED "$1"	  ;;
	-n|--quiet|--silent)  args="$args $1";;
	--posix)			  args="$args $1";;
	-r|--regexp-extended) args="$args $1";;
	-s|--separate)		args="$args $1";;
	-u|--unbuffered)	  args="$args $1";;
	-e)
		args="$args $1"
		shift
		args="$args '$1'"
	;;
	*)
		if [ "${1:0:2}" = "-i" ]
		then
			inplace="yes"
			extension="${1/-i/}"
		elif [ "$1" = "--" ]
		then
			args="$args $1"
			shift
			while [ "$1" ]
			do
				files[${#files[@]}]="$1"
				shift
			done
		else
				files[${#files[@]}]="$1"
		fi
esac
shift
done

# exécution de sed sur tous les fichiers si option "-i"
if [ "$inplace" = "yes" ]
then
for i in $(seq 0 $((${#files[@]} - 1)))
do
	file=${files[$i]}
	if [ "$extension" ]
	then
		backup="$file$extension"
	else
		backup="$file.backup.$$"
		if [ -e "$backup" ]
		then
			echo "Error : $backup exists :(" 1>&2
			exit 1
		fi
	fi
	cp -- "$file" "$backup"
	eval "$SED $args '$backup'" > "$file"
	if [ "$?" != "0" ]
	then
		mv -- "$backup" "$file"
		exit "$?"
	fi
	if [ -z "$extension" ]
	then
		rm -- "$backup"
	fi
done
else
eval "$SED $args"
fi

Share this post


Link to post
Share on other sites

Allez une question facile.

Comment faire pour faire un cat à l'envers ?

Par exemple

cat test
5
4
3
2
1
à l'envers
est comlètement
ce fichier

Je voudrais une façon de lire ça de bas en haut.

Share this post


Link to post
Share on other sites

Salut

cat monfichier|sort -r

par contre ça ne met pas en colone :)

et là jen e vois pas :(

a+

Share this post


Link to post
Share on other sites

Bah sort ça trie par ordre alpha, c'est pas le but :fume:

Effectivement, cat à l'envers, ça fait tac ;)

Bon une autre simple aussi :

Comment peut-on imprimer toutes les lignes d'un fichier en les précédant du numéro de ligne ?

cat test
Maître Corbeau, sur un arbre perché,
Tenait en son bec un fromage.
Maître Renard, par l'odeur alléché,
Lui tint à peu près ce langage :
"Hé ! bonjour, Monsieur du Corbeau.
Que vous êtes joli ! que vous me semblez beau !
Sans mentir, si votre ramage
Se rapporte à votre plumage,
Vous êtes le Phénix des hôtes de ces bois."
A ces mots le Corbeau ne se sent pas de joie;
Et pour montrer sa belle voix,
Il ouvre un large bec, laisse tomber sa proie.
Le Renard s'en saisit, et dit : "Mon bon Monsieur,
Apprenez que tout flatteur
Vit aux dépens de celui qui l'écoute :
Cette leçon vaut bien un fromage, sans doute. "
Le Corbeau, honteux et confus,
Jura, mais un peu tard, qu'on ne l'y prendrait plus. 

	 1  Maître Corbeau, sur un arbre perché,
 2  Tenait en son bec un fromage.
 3  Maître Renard, par l'odeur alléché,
 4  Lui tint à peu près ce langage :
 5  "Hé ! bonjour, Monsieur du Corbeau.
 6  Que vous êtes joli ! que vous me semblez beau !
 7  Sans mentir, si votre ramage
 8  Se rapporte à votre plumage,
 9  Vous êtes le Phénix des hôtes de ces bois."
10  A ces mots le Corbeau ne se sent pas de joie;
11  Et pour montrer sa belle voix,
12  Il ouvre un large bec, laisse tomber sa proie.
13  Le Renard s'en saisit, et dit : "Mon bon Monsieur,
14  Apprenez que tout flatteur
15  Vit aux dépens de celui qui l'écoute :
16  Cette leçon vaut bien un fromage, sans doute. "
17  Le Corbeau, honteux et confus,
18  Jura, mais un peu tard, qu'on ne l'y prendrait plus. 

Au moins 4 solutions dont trois en oneliners :yes:

Share this post


Link to post
Share on other sites

awk

awk '{printf("%4d %s\n", NR,$0)}' fichier.txt

sed

sed -e '=' fichier.txt | sed -r -e 'N; s/^/	/; s/ *(.{4})\n/\1 /'

bash

i=0; cat fichier.txt | while read line; do ((i=i+1)); n="	$i"; echo "${n: -4} $line"; done

... je cherche d'autres solutions ;)

EDIT :

perl

perl -p -e '$_ = sprintf("% 4d %s", $., $_)' fichier.txt

EDIT2 : modification du sed pour le simplifier

Share this post


Link to post
Share on other sites

Ah j'avais pas pensé à awk :craint:

Il y a (au moins) une autre solution aussi :smack:

Share this post


Link to post
Share on other sites

Ah! y'a nl aussi :

nl -w 4 -s " " fichier.txt

Pour rire, y'a grep :

grep -n "^" fichier.txt

Dans cet état c'est pas aussi joli, et si c'est pour utiliser sed/awk après ça sert à rien :D

EDIT : et cat alors !?

cat -n fichier.txt

EDIT2 :

en remarque, la version bash modifie les lignes qui démarrent ou finissent par des espaces

...et la version cat ne semble pas configurable pour avoir la même chose que les autres (ici 4 caractères pour le numéro de ligne et un espace de séparation).

Vous pouvez vérifier, les versions awk, sed, perl et nl sont comme il faut ;)

Share this post


Link to post
Share on other sites

A la demande générale (?)

Imaginons que j'ai une mosaïque d'images : 9x9, représantant chacune un 81ème d'une image finale.

par exemple des morceaux de carte d'un jeu en ligne comme "650 kilomètres" ...

11.jpg12.jpg ...

21.jpg22.jpg ...

...

+--------+--------+--------+--------+... +--------+
| 11.jpg | 12.jpg | 13.jpg | 14.jpg | ... | 19.jpg|
+--------+--------+--------+--------+... +--------+
| 21.jpg | 22.jpg | 23.jpg | 24.jpg | ... | 29.jpg|
+--------+--------+--------+--------+... +--------+
:												:	 :		  :
:												:	 :		  :
+--------+--------+--------+--------+... +--------+
| 91.jpg | 92.jpg | 93.jpg | 94.jpg | ... | 99.jpg|
+--------+--------+--------+--------+... +--------+

je fais un brutal wget couplé à un seq pour récupérer toutes les images :

(de mémoire :)

for i in seq `11 99`
do
  wget http://www.650kilometres.com/images/map_5/$i.jpg
done
rm ?0.jpg

Et maintenant je veux, en utilisant Imagemagick, en refaire une seule image (plus pratique :)

genre

7029a8f8e695b0ac07e0600eb0e96713.jpg

le tout, non pas en 5 lignes, en 4 lignes ni même en 2 lignes ... en 1 ligne de commande. Et même plus fort : en 1 commande ...

à vous de jouer !

(sinon essayez 650km c'est vraiment sympa ...)

Share this post


Link to post
Share on other sites

J'ai trouvé !

montage 650km_*.jpg -geometry 70x70 île.jpg

C'est 'achement puissant ImageMagick quand même !

Jfais un tit script ;)

edit :

for j in `seq 1 5`
do mkdir île_$j
cd île_$j
for i in `seq 11 99`
 do wget http://www.650kilometres.com/images/map_$j/$i.jpg
done
rm ?0.jpg
montage *.jpg -geometry 70x70 île_$j.jpg
cd ..
done

Au moins le serveur aura une bonne raison de ramer !

Share this post


Link to post
Share on other sites
J'ai vu que:

echo toto > titi # crée un fichier titi contenant toto
echo toto >> titi #met à la suite de titi un ligne contenant toto

Maintenant comment rajouter une ligne en tout début ou à un certain endroit d'un fichier?

Là c'est plus compliqué, il faut le faire en plusieurs fois avec un fichier intermédiaire. (Ou peut être qu'il y a des options dans les dernières versions de sed ou de perl, à voir).
hehe ben en voilà une nouvelle bonne idée de script à faire :transpi:

Aussitôt dit, aussitôt fait :pleure:.

C'est en perl, au début j'ai fait avec des while, mais après j'ai découvert Tie::File :incline: .

Bon en fait ça fait 2 lignes de code effectif, mais y'a de l'enrobage pour pouvoir l'utiliser dans n'importe quelle circonstances.

#!/usr/bin/perl -w
# Inserts input into file [at offset line, defaults to 0]

use strict;
use Tie::File;

if($#ARGV<0){print "Usage : $0 file [line]\n";exit}

tie my @file,'Tie::File',$ARGV[0] or die "\"$ARGV[0]\": $!";
my $i;$i=0 unless $i=$ARGV[1];

while(<STDIN>){splice @file,$i++,0,$_}

EDIT : mince j'allais oublier l'exemple :byebye:

 shell$ cat > file.txt
0
1
2
3
4
5
shell$ echo -e "voici deux\nlignes" | insert.pl file.txt 3
shell$ cat file.txt
0
1
2
voici deux
lignes
3
4
5
shell$

Share this post


Link to post
Share on other sites

Beaucoup plus simple (:francais:) une ligne de sed :

cat replace.sh 
#! /bin/sh
# usage : replace.sh num "pattern" file
# requirements : gnu sed, sh

LINE=$1
PATTERN=$2
FILE=$3

sed -i $LINE"s/^/$PATTERN\n/" $FILE

 sh replace.sh 3 "une ligne\nune autre" test 

 cat test 
1
2
une ligne
une autre
3
4
5
6
7
8
9
10

Share this post


Link to post
Share on other sites

Mais ça marche quand on utilise avec un pipe?

Genre si on veut insérer la sortie de dmesg à la ligne 1000 de /var/log/messages :francais:

(sinon c'est vrai qu'il fallait y penser)

Share this post


Link to post
Share on other sites

Re-up après presqu'1 an ...

là c'est un collègue qui me la pose, j'admet que j'ai pas la réponse :

c'est orienté KDE

il ouvre konsole avec plusieurs onglet, pour se connecter sur différentes machines

il aimerait que le nom de l'onglet colle avec la machine sur laquelle il se connecte.

je suis sandeman@mamachine

je fais ssh root@baga (ouais le jeu de mot :fume: )

l'onglet konsole devient root@baga

un petit bout de code ...

SESSION=`dcop $KONSOLE_DCOP currentSession`
dcop `dcopclient $KONSOLE_DCOP` $SESSION renameSession "foobar"

Share this post


Link to post
Share on other sites

j'ai une solution pas trop jolie, mais qui marchote :

#!/bin/bash

SESSION=$(dcop $KONSOLE_DCOP currentSession)
dcop `dcopclient $KONSOLE_DCOP` $SESSION renameSession $*
ssh $*
dcop `dcopclient $KONSOLE_DCOP` $SESSION renameSession `whoami`@`hostname`

que tu nommes kssh.sh, chmodé comme il faut, et tu t'en sers pour te connecter : kssh.sh user@machine

(ou kssh tout crout en mettant l'alias qui va bien)

la dernière ligne remet la bonne description au sortir du ssh.

Le problème me semble difficilement solvable autrement, sachant que ce qui s'exécute dans le shell est inaccessible à dcop. Donc que je tape "pouetpouet" ou "ssh" c'est la même. Quand au prompt, c'est bash qui le gère. dcop n'a pas accès à ce qui s'affiche dans la konsole.

:fume:

si quelqu'un à mieux, je suis preneur.

Share this post


Link to post
Share on other sites

Moi je modifie le titre des terminaux depuis le shell du PC distant :

if [ "$SSH_CLIENT" ] && [ "$SSH_CONNECTION" ] && [ "$SSH_TTY" ]
then
TITLE="[ssh:$(hostname)]"
print -Pn "\e]0;${TITLE}\a"
fi

(avec zsh, à voir si ça marche pareil avec d'autres shells)

Après, sous gnome-terminal automatiquement (les onglets ont le nom du titre de la fenêtre), sous konsole il suffit d'activer "Set tab title to match window title".

Share this post


Link to post
Share on other sites
Moi je modifie le titre des terminaux depuis le shell du PC distant :

if [ "$SSH_CLIENT" ] && [ "$SSH_CONNECTION" ] && [ "$SSH_TTY" ]
then
TITLE="[ssh:$(hostname)]"
print -Pn "\e]0;${TITLE}\a"
fi

(avec zsh, à voir si ça marche pareil avec d'autres shells)

Après, sous gnome-terminal automatiquement (les onglets ont le nom du titre de la fenêtre), sous konsole il suffit d'activer "Set tab title to match window title".

Pour les utilisateurs de bash, il faut signaler la variable PROMPT_COMMAND, qui est exécutée avant d'afficher le prompt.

Donc, mettre ça dans son .bashrc:

export PROMPT_COMMAND='echo -ne "33]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}7"'

Plus d'infos ici:

http://www.faqs.org/docs/Linux-mini/Xterm-Title.html

Share this post


Link to post
Share on other sites

×
×
  • Create New...