Scotch Linux arbre1 fly maison ScotchLinux... arbre

The Stream Editor

haut de la page

Présentation personnel

SED est, comme son nom l'indique, un éditeur de flux: il permet de manipuler un flux avec des expressions régulières. Celle-ci parfois complexe, par défaut son de la forme POSIX, peuvent être de la forme POSIX étendue. Il offre la possibilité de gérer plusieurs commande, et l'utilisation de block.

Traversons la page man de sed

Lorsqu' il n'y à pas d'exemple, ne soyez pas découragé ils existent peut-être plus bas (si non, commande console info sed)
Toutes la présente traductions peut contenir des erreurs, référez vous aux exemples, et entraînez vous.
En cas de doute: référez vous à la page de manuel, à la commande "info sed", ou ces lien SED documentation,sedfaq Cerains exemples sont complexes et j'espère ne pas me tromper dans leurs formulations

Description

Sed est un éditeur de flux. Un éditeur de flux est utilisé pour procéder à des opérations texte basics sur un flux d'entrée (un fichier ou un pipe). En quelques sortes similaire à un éditeur qui permet l'édition par scripts(comme ed), sed travaille en faisant seulement un passage au travers l'entrée(s), et est par conséquence plus efficace. Mais sed a la capacité de filtrer le texte dans un pipe ce qui le distingue des autres editeurs.

Les arguments

-n, --quiet, --silent
Supprimer les affichages automatique de l'espace du paterne.(Des exemples avec les commandes P)

-e script, --expression=script
Ajouter script au commande à exécuter.

Exemple:
echo salut toi |\
sed \
-e 's/salut//' \
-e 's/toi/moi/'

-f script-file, --file=script-file
Ajouter le contenu de script-file aux commande à exécuter.

Exemple 1:
echo -e "s/salut//\ns/toi/moi/" > test.sed ;\
echo salut toi |\
sed -f test.sed
Exemple 2:
echo -e "s/salut//\ns/toi/moi/" > test.sed ;\
echo salut toi |\
sed \
-f test.sed \
-e 's/moi/lui/'

--follow-symlinks
Suivre les liens symboliques quand le traitement est en place.(évite le déréférencement des liens (cf script suivant de --in-place)

-i[SUFFIX], --in-place[=SUFFIX]
Éditer les fichiers qui ont lieux (crée des sauvegarde si l'extension est fournie).
Exemple: C'est un petit script bash proposant une illustration de --follow-symlinks.

#!/bin/bash
function showfile(){
	local i_show
	ls -l --color=auto ./fichier*.*
	for i_show in "" ".lnk"; do
	echo "$1$i_show:	$(cat $1$i_show)	(on cat)"
	done
}
function separator(){
	local ARG;
	echo -n "go next"
	for j in $(seq 20); do
		test $j -ne 20 && ARG="-n" || ARG=""
		echo $ARG $1;
	done
}
if [[ ! -z $1  && $1 != "lnk" ]]; then
	echo "$1: bad argument"
	exit
fi
test -n "$1" && EXT=".$1"
for i in "fichier1" "fichier2"; do
	echo "salut toi $i" > $i
	ln -sv $i $i.lnk
	showfile $i
	test "$i" = "fichier1" && SED="--follow-symlinks " || SED=""
	sed -i $SED 's/salut//' $i.lnk;
	echo "operation:sed -i $SED's/salut//' $i$EXT:"
	showfile $i
	separator "="
	rm $i*
done
test -z "$1" && EXT="\'lnk\' as" || EXT="no"
echo "you can try with $EXT argument..."

-l N, --line-length=N
Spécifier la longueur de la ligne convertie pour la commande 'l'.

--posix
Ne pas utiliser les extension GNU.

-r, --regexp-extended
Utiliser les expressions régulières étendues.

Exemple 1( avec -r ):
echo l\'adresse ip: 127.0.0.1 salut |\
sed --regexp-extended \
's/^.*: *((\.{0,1}([0-9]{1,3})){4}).*/\1/g'
Exemple 2( sans -r ):
echo l\'adresse ip: 127.0.0.1 salut |\
sed \
's/^.*: *\(\(\.\{0,1\}\([0-9]\{1,3\}\)\)\{4\}\).*/\1/g'
le plus important ici est ":", rappelez vous que c'est pas humain: la machine n'a pas la vue, pas la peine de lui demander une vue d'ensemble.
regex POSIX non étendue
Je commence "^"
par n'importe quel caractère ".",
un certain nombre de fois,
même 0x "*" .
Je rencontre ":".
Je rencontre peut-être 0, un ou des espaces.
Je rencontre un première sous expression "\(" noté par sed \1,
puis une autre "\(" noté \2
qui commence ou non par le "."
Je rencontre une autre "\(" sous-expression \2
qui commence par un chiffre entre 0 et 9 "[0-9]"
qui se répète entre 1 et 3 fois \{1,3\}.
Je sorts de la dernières sous-expressions "\)" c'est l'expression sed '\3'.
Je sorts de la seconde sous expression "\)", expression sed '\2'.
Je répète la sous-expression 4x "\{4\}".
Je sorts de la première sous-expression "\)", expression sed '\1'.
Il se passe tout et n'importe quoi .*,....
Je substitue cette ligne à \1 hé! hop!!! \o/ bingo!!!

wikipedia expression rationnelle;documentation sed

-u, --unbuffered
Charger un taux minimum de données depuis l'entrée et vider les buffers de sortie le plus souvent.

--help
Montrer cette aide et sortir.

--version
Montrer les informations sur la version et sortir.

Si aucune des options -e, --expression, -f, ou --file sont données, alors le premier argument, non option, est passé comme un script sed à interpréter. Tous les autres arguments sont les noms des fichiers d'entrées; si aucuns fichiers d'entrées sont spécifié alors l'entrée standard(stdin) est lue.

Version information (voir la page man de sed, info sed ou sed --version).

Les commandes sed

Zero-Address 'commands'

: label
Label pour les commandes b et t.

#comment
Les commentaires s' étendent jusqu' à la prochaine nouvelle ligne (ou la fin d' un fragment de script --expression).

}
Fermeture d' acolade de block {}.

Exemple:
echo -e "toi\nblablabla\nhello\nsalut\ntoi\nbye\nblablabla\ntoi" |\
sed -e \
'{s/toi/moi/g}#remplace toi par moi'

Zero- or One- address commands

=
Afficher le numéro de la ligne actuel

Exemple:
echo -e "5\n4\n3\n2\n1" |\
sed -e '='

a \
text:ajouter à la fin 'text'(???).

``Append text, which has each embedded newline preceded by a backslash.'' (man sed)

i \
text:ajouter au début 'text'(???).

``Insert text, which has each embedded newline preceded by a backslash.'' (man sed)

Exemple:
echo -e "1\n2\n3\n4\n5" |\
sed \
-e '/2/ a\#une ligne ajoutée' \
-e '/2/ i\#une ligne insérée' #des lignes sont ajoutées

q [exit-code]
Quitter immédiatement le script sed sans procéder à plus d'entrée, sauf auto-print (-n, --quiet, --silent) n'est pas désactivé l'actuel espace paterne est affiché. le exit-code un argument GNU (relation avec --posix).

Exemple 1:
echo -e "1\n2\n3\n4\n5" |\
sed '/3/ q'
Exemple 2:
echo -e "1\n2\n3\n4\n5" |\
sed -n '/7/ q 1';\
echo $? #($? valeur de return, ici q 1 )
Exemple 3:
echo -e "1\n2\n3\n4\n5" |\
sed -n --posix '/7/ q 1';\
echo $?
Une erreur ?
C'est normal: The exit code argument is a GNU extension.

Q [exit-code]
Quitter immédiatement le script sed sans procéder à plus d'entrée. C' est une extension GNU.

Exemple:
echo -e "1\n2\n3\n4\n5" |\
sed '/3/ Q';
Pas la peine de tester sed --posix '/3/ Q' Q est une extension GNU.

r filename
Ajouter le texte lu depuis filename.

Exemple:
echo -e "6\n7\n8\n9\n10" > test.sed; \
echo -e "1\n2\n3\n4\n5\nbye" |\
sed '/5/ r test.sed'

R filename
Ajouter une ligne lue depuis filename. chaque invocation de la commande lie une ligne de le fichier (sans se replacer au début). C'est une extension GNU.

Exemple:
echo -e "6\n7\n8\n9\n10" > test.sed; \
echo -e "1\n2\n3\n4\n5\nbye" |\
sed '/[1-5]/ R test.sed'

Les commandes qui accepte des rangs

{
Début d'un block de commandes (ce fini par un }).

Exemple:
echo -e "toi\nblablabla\nhello\nsalut\ntoi\nbye\nblablabla\ntoi" |\
sed -e \
'/hello/,/bye/ {s/toi/moi/g}#remplace toi par moi entre hello et bye'

b label
Se brancher a label; si label est omis, ce brancher à la fin du script.

Exemple:
echo -e "toi\nlui\nhello\nsalut\ntoi\nbye\nblablabla\ntoi" |\
sed \
-e ':to_cool s/lui/cool/' \
-e 's/toi\|\(bla.*\)/lui/' \
-e '/lui/ b to_cool'

t label
Si s/// effectue une bonne substitution depuis que la dernière ligne a été lue ET depuis la dernière t ou T, alors se brancher au label; si label est omis, ce brancher à la fin du script.

Exemple:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed \
-e ':sub s/msg/______/' \
-e 's/hello\|bye/msg/' \
-e 't sub'

T label
Si aucune s/// ne s'effectue, depuis que la dernière ligne est été lue ET depuis une commande t ou T, alors se brancher à à label; si label est omis alors se brancher à la fin du script. C'est une extension GNU.

Exemple:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed \
-e ':sub s/msg/______/' \
-e 's/hello\|bye/msg/' \
-e 'T' \
-e 'b sub'

c \
text:Remplacer la ligne sélectionnée par le text(???).

``Replace the selected lines with text, which has each embedded newline preceded by a backslash.'' (man sed)

Exemple:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed -e '/bonjour/,/toi/ c \vide'

d
Supprimer l'espace du paterne, démarrer un nouveau cycle.

Exemple 1:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed -e '1d'
Exemple 2:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed -e '2,4 d'
Exemple 3:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed -e '/bonjour/,/toi/d'
Exemple 4:
echo -e "hello\nbonjour\nà\ntoi\nbye" |\
sed -e '/bonjour/,/toi/!d' #sélection inverse

D
Supprimer jusqu'à la nouvelles ligne intégrées dans l'espace du paterne. Commencer un nouveau cycle, mais arrêter de lire depuis l'entrée si il y a encore des données dans l'espace du paterne.( Un exemple avec P )

h H
Copier/ajouter l'espace du paterne vers l'espace détenteur.

g G
Copier/ajouter l'espace détenteur vers l'espace du paterne.

x
Echanger les contenu des espaces détenteur et paterne.

Exemple
Afficher avec une décalage:
echo -e "salut\ntoi\nca\nva\n???" |\
sed -n \
-e 's/^\(.*\)/<\1>/' \
-e 'i à:' \
-e 'P' \
-e 'i affichage:' \
-e 'x' \
-e 'P'

l
Lister la ligne actuel dans forme "visuellement non ambiguë."

l width
Lister la ligne actuel dans forme "visuellement non ambiguë, la couper a width caractères. C'est une extension GNU.

Exemple:
echo -e "salut" |\
sed 'l 3'

n N
Lire/ajouter la ligne suivante de l'entrée dans l'espace du paterne.

Exemple(Faire une ligne en retirant les paternes en supprimant les patrenes multiples):
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nca\nca\nca\nva\nva" | \
sed \
-e ':start N' \
-e 's/^ //' \
-e 's/\(^\| \)\(.*\)\n\2/ \2/' \
-e 's/\n/ /' \
-e 't start'

p
Afficher l' actuelle espace du paterne.

P
Afficher jusqu'à la nouvelle ligne intégrée de l'espace du paterne.

Exemple 1(Afficher le doublon, supprimer ce qui ne l'est pas)
echo -e "salut\nsalut\ntoi\nc'est\nc'est\nc'est\nmoi" |\
sed -n \
-e '$!N' \
-e 's/^\(.*\)\n\1/\1/' \
-e 'T del' \
-e 'P' \
-e ':del D'
Exemple 2(Supprimer le doublon, afficher ce qui ne l'est pas ou supprimer le paterne.)
echo -e \
"salut\nsalut\nsalut\nsalut\ntoi,\nc'est\nc'est\nmoi" | \
sed \
-e '$!N' \
-e 's/^\(.*\)\n\1//' \
-e 't del' \
-e 'P' \
-e ':del D'
Exemple 3(supprimer le doublon et le paterne ,affichier ce qui ne l'est pas.)
echo -e "salut\nsalut\ntoi\nc'est\nc'est\nc'est\nmoi" |\
sed -n \
-e '$!N' \
-e 's/^\(.*\)\n\1//' \
-e 'T nl' \
-e 'D' \
-e ':nl P'

s/regexp/replacement/
Tente d'itdentifier regexp dans l'espace du paterne. Si l'operation réussie, remplace la portion identifiée avec le repacement. le replacement peut contenir le caractère spécial & pour référer à cette portion identifiée de l'espace du paterne, et les caractères spéciaux \1 à \9 réfèrent aux expressions correspondant aux sous expressions de regexp.

S' il est possible de faire correspondre dans tout un flux avec 'g', ou seulement un certain nombre de fois( s///g, s///nombre), il faut que vous sachiez que d'autre commande son possible dans la substitution (info sed, 3.5 The `s' Command). C'est pour cela que vous devriez faire un tour dans info sed. En plus d'y trouver des info sur les modifeur de cette commande, il y à de la documentation sur les modification de casse (upper to lower, lower to upper...), et plus encore...

Exemple:
echo 'Yo!!!' |\
sed -e 's/Yo/hey/'

w filename
Ecrit l'espace du paterne actuel dans filename.

W filename
Ecrit les premières lignes de l'espace du paterne actuel dans filename. C'est une extenstion GNU.

y/source/dest/
Transliter les caractères dans l'espace du paterne qui apparaisse dans source au caractère corespondant de dest.

Exemple
echo "1d77f" |\
sed -e \
'{
y/abcdef/ABCDEF/;
s/\(.*\)/0x\1/
}'

Adresses

Les commandes de sed peuvent être données sans adresses, dans quel cas la command sera éxécutée pour toutes les lignes d'entrées; avec une adresse, la command sera seulement éxécutée sur les lignes d'entrées qui correspondent à cette adresse; ou avec 2 adresses, dans quel cas la command sera executée pour toutes entrées qui correspondent à la série inclusive de lignes commançant par la première adresse et continuant jusqu'à la seconde adresse.
3 choses à noter à propos des intervalles d'adresses: la syntaxe est addr1,addr2 (i.e., les adresses sont séparées par une virgule; la ligne à laquelle correspond addr1 sera toujour accéptée, même si addr2 seltionnent une ligne en amont; et si addr2 est une regexp, elle ne sera pas testée sur l'adresse à laquelle addr1 correspond.

Après les adresses (ou intervalle d'adresse), et avant la command, un ! peut être introduit, ça spécifie que la commande sera seulement éxécutée si les adresses (ou l'intervalle d'adresses) ne correspondent pas.

Les pérsents type d'adressages sont supportées:

number
Identifie seulement sur la ligne spécifiée par number.

Exemple:
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n '5p'

first~step
Identifier toutes les step en commançant par la ligne first. Par exemple ``sed -n 1~2p'' affichera toutes les lignes impaires du flux d'entrée, et les adresses 2~5 identifira toutes les 5 lignes, en commançant par la 2ème. first peut-être 0; auquel cas, sed opère comme s'il aurait été égale à step.(c'est une extention)

Exemple 1:
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n '2~2p'
Exemple 2:
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n '0~2p'

$
Identifie la dernière ligne.

Exemple:
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n -e '$p'

/regexp/
Identifie les lignes correspondantes à l'expression régulière regexp.

Exemple:
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n '/salut/ {s/\(sa\)/\1\n/;P}'

\cregexpc
Identifie les lignes correspondantes à l'expression régulière regexp les c peuvent être n'importe quel caractère.

Exemple:
echo -e "salut\nsalut\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n -e '\e^[a-z]\{2\}$ep'

\cregexpcI
Comme précedent mais est insensible à la casse. C'est une extention GNU. (info sed, 3.2 Selecting lines with `sed')

\cregexpcM
Le modifieur M à l'identifieur d' expression fais correspondre respectivement (en addition de la réaction normal) la ligne vide avant et après une nouvelle ligne. Il y à des séquences de caractères spéciaux (`\`' et `\'') qui toujour identifie le début et la fin du buffer. C'est une extension GNU.

The `M' modifier to regular-expression matching is a GNU `sed' extension which causes `^' and `$' to match respectively (in addition to the normal behavior) the empty string after a newline, and the empty string before a newline. There are special character sequences (`\`' and `\'') which always match the beginning or the end of the buffer. `M' stands for `multi-line'.(info sed, 3.2 Selecting lines with `sed')

GNU sed supporte quelques formes spéciales 2-adress:

0,addr2
Commence à "la première adresse identifiée" , jusqu'à ce que addr2 soit atteinte. C'est similaire à 1,addr2, à l'éxéption que si addr2 est identifiée à la toute première ligne de l'entrée, la forme 0,addr2 sera à la fin de son intervalle, à l'encontre de la forme 1,addr2, qui est le début de l'intervalle. Ca fonctionne seulement quand addr2 est une expression régulière.

``Start out in "matched first address" state, until addr2 is found. This is similar to 1,addr2, except that if addr2 matches the very first line of input the 0,addr2 form will be at the end of its range, whereas the 1,addr2 form will still be at the beginning of its range. This works only when addr2 is a regular expression'' (man sed)

Exemple 1:
echo -e "salut\ntoi\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n '1,/salut/p'
Exemple 2:
echo -e "salut\ntoi\nsalut\nsalut\ntoi\nca\nca\nva\nva" |\
sed -n '0,/salut/p'

addr1,+N
Identifira addr1 et les N lignes suivantes.

Exemple:
echo -e "salut\ntoi\nsalut\nsalut\ntoi\nca\nca\nva\nva" |
sed -n '/toi/,+3p'

addr1,~N
Identifira addr1 et les lignes suivantes jusqu'à ce que la prochain numérot de ligne soit un multiple de N.

Exemple:
echo -e "\nsalut\nsalut\nca\ntoi\nca\nva\nva\nbien\ndit\nmoi" |\
sed -n '/toi/,~3p'

REGULAR EXPRESSIONS

POSIX.2 BREs devrait être supporté, mais il ne l'est pas complètement pour des raisons problèmes de pérformances. La séquence \n dans une expression régulière correspond à un caractère de nouvelle ligne, et de même pour \a, \t et d' autres séquences.

info sed: pour plus d'information, d'autre exemple...

Illustration

mush
haut de la page

Après avoir réalisé cette page il m'est venue l'idée de lui offrir une illustration. J' ai pas mal cherché une solution qui était sous mon nez.

L'original

J'ai Réalisé un script awk afin de changer de playlist avec nyxmms2. Ce script Permet d'aller à la playlist suivante ou précédente suivant l'argument passé. S' il n'y à pas de playlist avant ou après, il retourne à la dernière ou la première.

le script awk:
l'original
nyxmms2 playlist list | \
awk \
	-v cle="$1" '{
		set=0;
		if(cle=="prev"){ set=-1 }
		if(cle=="next"){ set=1 }
		playlist[NR]=$0
	}END{
		for(i=1;i<=NR;i++){
			if(playlist[i] ~ /^\*/){
				if( i+set > NR ){
					sub(/[ ]+/,"",playlist[1]);
					print playlist[1];
					break;
				}
			if( i+set == 0 ){
				sub(/[ ]+/,"",playlist[NR]);
				print playlist[NR]
				break;
			}
			sub(/[ ]+/,"",playlist[i+set]);
                        print playlist[i+set]
		}
	}
}')"

Ce court script, met une valeur en fonction de l'argument:
prev = -1( playlist précédente )
next = +1( playlist suivante )
tout en enregistrant le flux.
il analyse ligne par ligne le flux enregistré pour afficher la valeur qui sera passée à nyxmms2.

Avec SED

Sed n' a pas d' instruction, il ne connait que des commandes. Donc, j'ai due faire un script pour next, et un script pour prev que voici:

Prev

prev
#sed -ne
s/^[ ]*// #supprimer les espaces vides du debut permet l'appelle d'un argument entre double quotes
/^\*/ {
	x;
	/^$/ b end;
	P;
	q;
	}
:end
$p
x

Se script ce démarre avec l' option -n( --quiet ) car on affichera quand ça nous plais.

/^\*/: à l'adresse ou le paterne commence par "*", exécuter le block.
dans le block:
échanger les espaces.
la ligne vide renvoie à "end".
on afficher et quitter.
$p: identifie la dernière ligne à indentifier
x: on échange les paternes.

Je ne peux pas vraiment expliquer le "$p", mais je suppose que c'est lié au propriété du flux:
Comme je quitte le flux avant d'avoir atteint la fin, il ne l'affiche pas.

next

Le script sed pour aller à la playlist suivante est un peut plus long:

#premier titre
/^\*/	{
		N;
		s/.*\n//;
		s/^[ ]*//;
		P;
		q;
	}
:start $!N
s/^\(.*\);;.*\(\n.*\)/\1\2/
s/\n/;;/
/\*/ b end;
t start
:end
s/\(.*\);;.*/\1/
s/^[ ]*//
$P

A la ligne qui commence par "*",
on ajoute une ligne
on substitue jusqu'à la nouvelle ligne par rien
on afficher, et on quitte
branchement start on ajoute une ligne (sauf la dernière)
on substitue jusqu'à ";;"et après \n(inclus) par avant ";;" et après (inclus) "\n"
on substitue "\n" par ";;"
lorsque le paterne contient "*" on va à end, si non lorsque la dernière substitution a fonctionné, on retourne à start.
à end, on substitue le paterne par ce qu'il y a avant les ";;", et on affiche la dernière ligne

mushEt Voila...

reste plus qu' a :"nyxmms2 playlist list | sed -nf script.sed"

Je vais vous le dire comme ça: "chez moi ça marche", car je ne l'ai testé qu'avec 5 titres.