Quels conseils généraux avez-vous pour jouer au golf à Sed? Je recherche des idées qui peuvent être appliquées aux problèmes de code-golf et qui sont également au moins quelque peu spécifiques à sed (par exemple, "supprimer les commentaires" n'est pas une réponse).
Veuillez poster un pourboire par réponse.
F
commande n'a jamais fonctionné. Quelqu'un sait-il pourquoi?F
fonctionne sur mon GNU sed (test Debian). Il s'imprime juste-
si vous lisez depuis stdin, bien sûr, mais c'est prévu. De quoi tirez-voussed -e 'F;Q' /etc/hostname
?char 1: unknown command: F
. Je dois mettre à jour sed peut-être; Quelle version avez-vous? LaL
commande ne fonctionne pas non plus, mais elle est de toute façon inutile depuis qu'elle-l n
existe. Tout le reste mentionné sur le site de GNU sed fonctionne.bash, sed and dc
pour tous ceux qui veulent parler et poser des questions sur ces langues. Faisons une communauté!Réponses:
Si vous devez utiliser des étiquettes, vous voudrez certainement que les noms de vos étiquettes soient aussi courts que possible. En fait, poussé à l'extrême, vous pouvez même utiliser la chaîne vide comme nom d'étiquette:
la source
:
nécessite désormais une étiquette.La documentation GNU sed décrit la
s
commande comme "le couteau suisse de sed" . Mais si tout ce que vous voulez faire est de remplacer toutes les instances d'un caractère par un autre, alors lay
commande est ce dont vous avez besoin:est un caractère plus court que:
la source
y/12/21/
Pensez à utiliser la syntaxe regex étendue (dans GNU sed). L'
-r
option coûte un octet en notation, mais l'utiliser une seule fois pour éliminer les barres obliques inverses d'une paire\(...\)
a déjà payé.la source
-r
semble êtresed
spécifique à GNU .+
,?
,{}
et|
dans les matches regex, car aucune barre oblique inverse sont nécessaires non plus .-E
fonctionne comme un alias-r
dans de nombreusessed
implémentations si je me souviens bien.Lors d'un remplacement répété dans une boucle:
il n'est généralement pas nécessaire de le remplacer globalement, car la boucle finira par remplacer toutes les occurrences:
Notez également l'extension GNU ci-dessus: une étiquette peut avoir un nom vide, économisant ainsi des octets plus précieux. Dans d'autres implémentations, une étiquette ne peut pas être vide et le saut sans étiquette transfère le flux à la fin du script (c'est-à-dire le même que
n
).la source
:
)Il n'y a pas d'arithmétique intégrée, mais les calculs peuvent être effectués en décimal unaire ou codé unaire. Le code suivant convertit la décimale en UCD, avec x comme unité et 0 comme séparateur de chiffres:
et voici la conversion en décimal:
Ceux-ci sont tous deux tirés d' une réponse à "Multipliez deux nombres sans utiliser de nombres" .
Unaire ancien simple peut être converti en utilisant cette paire de boucles de cette réponse en "{nombres bouclés};" , où se trouve l'unité
;
. J'ai utilisév
etx
pour correspondre à Roman pour5
et10
;b
vient de "bis".la source
/[;v]/!s/\b/0/2
, qui doit être changée en/[;v]/!s:x\+:&0:
pour qu'elle fonctionne. Voir ici .Comme mentionné dans
man sed
(GNU), vous pouvez utiliser n'importe quel caractère comme délimiteur pour les expressions régulières en utilisant la syntaxeoù
%
est un espace réservé pour n'importe quel caractère.Ceci est utile pour des commandes comme
qui sont plus courts que
Ce qui est mentionné dans le manuel GNU sed, mais pas dans,
man sed
c'est que vous pouvez également changer les délimiteurs des///
ety///
.Par exemple, la commande
supprime toutes les barres obliques de l'espace de motif.
la source
S'il n'est pas explicitement interdit par la question, le consensus pour cette méta-question est que l'entrée numérique peut être unaire. Cela vous permet d'économiser les 86 octets décimaux à unaire selon cette réponse .
la source
En développant cette réponse de pointe , concernant les conversions entre les formats de nombres décimaux et unaires simples, je présente les méthodes alternatives suivantes, avec leurs avantages et leurs inconvénients.
Décimal à unaire simple: 102 + 1 (indicateur r) = 103 octets. J'ai compté
\t
comme un onglet littéral, comme 1 octet.Essayez-le en ligne!
Avantage: il est 22 octets plus court et en plus, il fonctionne avec des entiers négatifs en entrée
Inconvénient: il écrase l'espace d'attente. Cependant, comme il est plus probable que vous ayez besoin de convertir l'entier d'entrée au début du programme, cette limitation est rarement ressentie.
Ordinaire unaire à décimal: 102 + 1 (indicateur r) = 103 octets
Essayez-le en ligne!
Avantage: il est plus court de 14 octets. Cette fois, les deux versions de pourboire fonctionnent en entrée pour les entiers négatifs.
Inconvénient: il écrase l'espace d'attente
Pour un défi compliqué, vous devrez adapter ces extraits pour qu'ils fonctionnent avec d'autres informations pouvant exister dans l'espace modèle ou l'espace réservé, en plus du nombre à convertir. Le code peut être joué plus, si vous savez que vous ne travaillez qu'avec des nombres positifs ou que le zéro seul ne sera pas une entrée / sortie valide.
Un exemple d'une telle réponse de défi, où j'ai créé et utilisé ces extraits, est l' inverse d'un nombre (1 / x) .
la source
s:\n|@$::g
. tio.run/##K05N@f@/2ErX3krNwIpL30G/…-r
, mais avec un nouveau consensus, les drapeaux ne comptent pas dans le décompte de toute façon, et cela ne gâche pas l'espace d'attente)/\n/ta
en/\n/t
, vous économisez 1 octet pour obtenir 96Parlons des commandes
t
etT
, bien qu'elles soient expliquées dans la page de manuel, il est facile de les oublier et d'introduire des bogues accidentellement, surtout lorsque le code se complique.Déclaration de page de manuel pour
t
:Exemple montrant ce que je veux dire: disons que vous avez une liste de nombres et que vous voulez compter le nombre de négatifs. Code partiel ci-dessous:
Ça a l'air bien, mais ça ne l'est pas. Si le premier nombre est positif, ce code pensera toujours qu'il était négatif, car le saut effectué via
t
pour la première ligne d'entrée est effectué malgré tout, car il y a eu unes
substitution réussie lorsque nous avons initialisé le compteur! Le correct est:/-/b increment_counter
.Si cela vous paraissait facile, vous pourriez tout de même être dupe lorsque vous effectuez plusieurs sauts d'avant en arrière pour simuler des fonctions. Dans notre exemple, le
increment_counter
bloc de code utiliserait certainement beaucoup des
commandes. Revenir avecb main
pourrait faire tomber un autre check dans "main" dans le même piège. C'est pourquoi je reviens habituellement des blocs de code avecs/.*/&/;t label
. C'est moche, mais utile.la source
Au lieu d'effacer l'espace de motif avec
s/.*//
, utilisez laz
commande (en minuscules) si vous optez pour GNU sed. Outre le nombre d'octets inférieur, il présente l'avantage de ne pas démarrer le cycle suivant comme led
fait la commande , ce qui peut être utile dans certaines situations.la source
.
).Je sais que c'est un vieux thread, mais je viens de trouver ces convertisseurs décimaux maladroits en UCD, avec près d'une centaine d'octets, certains gâchant même l'espace d'attente ou nécessitant des défauts particuliers
sed
versions .Pour la décimale en UCD, j'utilise (68 octets; l'ancien meilleur affiché ici 87 octets)
UCD en décimal est (également 66 octets; ancien meilleur affiché ici 96)
\n
dans le remplacement n'est pas portable. Vous pouvez utiliser un caractère différent à la place et enregistrer deux octets, mais vous aurez besoin de plus d'octets pour supprimer l'appendice au lieu deP;d
; voir remarque suivante. Ou, si votre espace d'attente est vide, faitesG;s/$/9876543210/
sans pénalité d'octet.s/\n.*//
au lieu deP;d
.sed
versions dela source
sed
versions qui violent la norme POSIX.Lisez l'intégralité de l'entrée en même temps avec
-z
Souvent, vous devez opérer sur l'ensemble de l'entrée à la fois au lieu d'une ligne à la fois. La
N
commande est utile pour cela:... mais généralement vous pouvez l'ignorer et utiliser le
-z
drapeau à la place.Le
-z
drapeau fait que sed utilise NUL (\0
) comme séparateur de ligne d'entrée au lieu de\n
, donc si vous savez que votre entrée ne contiendra pas\0
, il lira toutes les entrées à la fois comme une seule "ligne":Essayez-le en ligne!
la source
Ajouter une nouvelle ligne dans un octet
La
G
commande ajoute une nouvelle ligne et le contenu de l'espace d'attente à l'espace modèle, donc si votre espace d'attente est vide, au lieu de cela:Tu peux le faire:
Ajouter une nouvelle ligne en trois octets
La
H
commande ajoute une nouvelle ligne et le contenu de l'espace de motif à l'espace d'attente, etx
échange les deux, donc si votre espace d'attente est vide, au lieu de cela:Tu peux le faire:
Cela polluera votre espace de retenue, donc cela ne fonctionne qu'une seule fois. Cependant, pour deux octets supplémentaires, vous pouvez effacer votre espace de modèle avant de permuter, ce qui représente toujours une économie de deux octets:
la source
Dans sed, la chose la plus proche d'une fonction que vous pouvez avoir est une étiquette. Une fonction est utile car vous pouvez exécuter son code plusieurs fois, économisant ainsi beaucoup d'octets. Dans sed, cependant, vous devrez spécifier l'étiquette de retour et en tant que tel, vous ne pouvez pas simplement appeler cette "fonction" plusieurs fois dans votre code comme vous le feriez dans d'autres langues.
La solution de contournement que j'utilise consiste à ajouter dans l'une des deux mémoires un indicateur, qui est utilisé pour sélectionner l'étiquette de retour. Cela fonctionne mieux lorsque le code de fonction n'a besoin que d'un seul espace mémoire (l'autre).
Exemple montrant ce que je veux dire: extrait d'un de mes projets pour écrire un petit jeu dans sed
Les étiquettes doivent bien sûr être regroupées en une seule lettre, j'ai utilisé des noms complets pour une meilleure explication.
la source
Les expressions rationnelles vides sont équivalentes à l'expression régulière rencontrée précédemment
(merci à Riley de l' avoir découvert à partir d'une soumission anagol )
Voici un exemple où nous sommes chargés de créer 100
@
s dans un tampon vide.La deuxième solution est plus courte d'un octet et utilise le fait que les expressions régulières vides sont remplies avec la dernière expression régulière rencontrée. Ici, pour la deuxième substitution, le dernier regex était
.*
, donc le regex vide ici sera rempli.*
. Cela fonctionne également avec les expressions rationnelles dans/conditionals/
.Notez qu'il s'agit de l' expression régulière rencontrée précédemment , donc les éléments suivants fonctionneraient également.
La regex vide est remplie au
@*
lieu de$
cars/$/@/
n'est jamais atteinte.la source
Étape presque inutile:
Cela ne traduit
A
àB
ety
àz
(... et-
à-
;), mais rien d' autre, sireviendra simplement:
Vous pouvez vous assurer que ce sera inutile, pour l' échantillon en utilisant cette sur des valeurs hexadécimaux minuscules (ne contenant que
0
,1
,2
,3
,4
,5
,6
,7
,8
,9
,a
,b
,c
,d
,e
ouf
.)la source
sed '; ;/s/b;y|A-y|B-z|;s ;s/ //; ; ;' <<<'Hello world'
(Pourquoi cela ne supprime -t-il pas l'espace?)