Welche allgemeinen Tipps haben Sie zum Golfen in Sed? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme anwenden lassen und die zumindest etwas spezifisch für sed sind (z. B. "Kommentare entfernen" ist keine Antwort).
Bitte posten Sie einen Tipp pro Antwort.
F
Befehl hat nie funktioniert. Weiß jemand warum?F
arbeitet an meiner GNU sed (Debian-Test). Es wird-
natürlich nur gedruckt, wenn von stdin gelesen wird, aber das wird erwartet. Von was bekommstsed -e 'F;Q' /etc/hostname
duchar 1: unknown command: F
. Ich muss sed vielleicht updaten; welche version hast du DerL
Befehl funktioniert auch nicht, aber er ist sowieso nutzlos, da er-l n
existiert. Alles andere, was auf der Site von GNU sed erwähnt wird, funktioniert.bash, sed and dc
für alle geöffnet, die über diese Sprachen sprechen und fragen möchten. Lasst uns eine Community bilden!Antworten:
Wenn Sie Beschriftungen verwenden müssen, möchten Sie sicher, dass Ihre Beschriftungsnamen so kurz wie möglich sind. Im Extremfall können Sie die leere Zeichenfolge sogar als Labelnamen verwenden:
quelle
:
Benötigt jetzt ein Etikett.Die GNU sed Dokumentation beschreibt den
s
Befehl als "sed's Swiss Army Knife" . Wenn Sie jedoch nur alle Instanzen eines Zeichens durch ein anderes ersetzen möchten, benötigen Sie den folgendeny
Befehl:ist ein Zeichen kürzer als:
quelle
y/12/21/
Erwägen Sie die Verwendung einer erweiterten Regex-Syntax (in GNU sed). Die
-r
Option kostet ein Byte in der Wertung, aber die einmalige Verwendung, um die Backslashes eines Paares zu eliminieren,\(...\)
hat sich bereits bezahlt gemacht.quelle
-r
der GNU-sed
spezifisch zu sein scheint .+
,?
,{}
und|
in Regex -Übereinstimmungen, da keine Schrägstriche entweder benötigt werden.-E
funktioniert als Alias für-r
vielesed
Implementierungen, wenn ich mich richtig erinnere.Beim wiederholten Ersetzen in einer Schleife:
Es ist normalerweise nicht erforderlich, global zu ersetzen, da die Schleife schließlich alle Vorkommen ersetzt:
Beachten Sie auch die GNU-Erweiterung oben: Ein Label kann einen leeren Namen haben, wodurch mehr wertvolle Bytes gespart werden. In anderen Implementierungen kann ein Label nicht leer sein, und das Springen ohne Label überträgt den Fluss an das Ende des Skripts (dh dasselbe wie
n
).quelle
:
Es gibt keine eingebaute Arithmetik, aber Berechnungen können in unären oder unärkodierten Dezimalzahlen durchgeführt werden. Der folgende Code konvertiert Dezimalzahlen in UCD mit x als Einheit und 0 als Zifferntrennzeichen:
und hier ist die Umrechnung zurück in dezimal:
Diese beiden Werte stammen aus einer Antwort auf "Multiplizieren Sie zwei Zahlen ohne Verwendung von Zahlen" .
Mit diesem Schleifenpaar aus dieser Antwort zu "{Curly Numbers};" kann eine einfache alte Unäre konvertiert werden. , wo das Gerät ist
;
. Ich habev
und verwendetx
, um Roman für5
und zu entsprechen10
;b
kommt von "bis".quelle
/[;v]/!s/\b/0/2
, die geändert werden muss,/[;v]/!s:x\+:&0:
damit sie funktioniert. Sehen Sie hier .Wie in
man sed
(GNU) erwähnt, können Sie mithilfe der Syntax ein beliebiges Zeichen als Begrenzer für reguläre Ausdrücke verwendenwo
%
ist ein Platzhalter für ein beliebiges Zeichen.Dies ist nützlich für Befehle wie
die sind kürzer als
Was ist in der erwähnt wird GNU sed Handbuch aber nicht in
man sed
ist , dass Sie die Trennzeichen von ändern könnens///
undy///
wie gut.Zum Beispiel der Befehl
Entfernt alle Schrägstriche aus dem Musterbereich.
quelle
Wenn die Frage dies nicht ausdrücklich verbietet, besteht der Konsens für diese Meta-Frage darin, dass die numerische Eingabe unär sein kann. Dies erspart Ihnen die 86 Bytes Dezimalzahl nach dieser Antwort als unär .
quelle
Um diesen Tipp bezüglich der Konvertierungen zwischen dezimalem und einfachem unärem Zahlenformat zu erweitern, präsentiere ich die folgenden alternativen Methoden mit ihren Vor- und Nachteilen.
Dezimal bis unär: 102 + 1 (r Flag) = 103 Bytes. Ich habe
\t
als 1-Byte-Tabulator gezählt .Probieren Sie es online!
Vorteil: Es ist 22 Bytes kürzer und arbeitet zusätzlich mit negativen ganzen Zahlen als Eingabe
Nachteil: es überschreibt den Laderaum. Da es jedoch wahrscheinlicher ist, dass Sie die Eingabe-Ganzzahl gleich zu Beginn des Programms konvertieren müssen, ist diese Einschränkung selten zu spüren.
Einzahlig bis dezimal: 102 + 1 (r Flag) = 103 Bytes
Probieren Sie es online!
Vorteil: es ist 14 Bytes kürzer. Dieses Mal funktionieren beide Tippversionen für negative Ganzzahlen als Eingabe.
Nachteil: es überschreibt den Laderaum
Bei einer komplizierten Herausforderung müssen Sie diese Ausschnitte anpassen, um mit anderen Informationen zu arbeiten, die neben der zu konvertierenden Zahl möglicherweise im Muster- oder Haltebereich vorhanden sind. Der Code kann mehr gespielt werden, wenn Sie wissen, dass Sie nur mit positiven Zahlen arbeiten oder dass eine Null allein keine gültige Eingabe / Ausgabe ist.
Ein Beispiel für eine solche Herausforderungsantwort, bei der ich diese Ausschnitte erstellt und verwendet habe, ist der Kehrwert einer Zahl (1 / x) .
quelle
s:\n|@$::g
. tio.run/##K05N@f@/2ErX3krNwIpL30G/…-r
, aber mit neuem Konsens werden Flaggen sowieso nicht für das Bytecount gezählt, und der Laderaum wird nicht durcheinander gebracht.)/\n/ta
nach ändern/\n/t
, sparen Sie 1 Byte, um 96Lassen Sie uns über die Befehle
t
und sprechenT
, die zwar in der Manpage erklärt werden, aber leicht zu vergessen sind und versehentlich Fehler verursachen, insbesondere wenn der Code kompliziert wird.Manpage-Statement für
t
:Beispiel, das zeigt, was ich meine: Nehmen wir an, Sie haben eine Liste mit Zahlen und möchten zählen, wie viele Negative es gibt. Teilcode unten:
Sieht ok aus, ist es aber nicht. Wenn die erste Zahl positiv ist, denkt dieser Code immer noch, dass sie negativ war, da der Sprung über
t
die erste Eingabezeile unabhängig davon ausgeführt wird, das
bei der Initialisierung des Zählers eine erfolgreiche Substitution stattgefunden hat! Richtig ist:/-/b increment_counter
.Wenn dies einfach erscheint, können Sie sich dennoch täuschen lassen, wenn Sie mehrere Sprünge vor und zurück ausführen, um Funktionen zu simulieren. In unserem Beispiel würde der
increment_counter
Codeblock sicher vieles
Befehle verwenden. Wenn Sie mit zurückkehren,b main
könnte ein weiterer Check in "main" in dieselbe Falle geraten. Deshalb kehre ich normalerweise von Codeblöcken mit zurücks/.*/&/;t label
. Es ist hässlich, aber nützlich.quelle
s/.*//
Verwenden Sie denz
Befehl (in Kleinbuchstaben), wenn Sie mit GNU sed arbeiten, anstatt den Musterbereich mit zu löschen. Neben der geringeren Byteanzahl hat dies den Vorteil, dass der nächste Zyklus nicht wie mit dem Befehl gestartetd
wird, was in bestimmten Situationen nützlich sein kann.quelle
.
).Ich weiß, dass dies ein alter Thread ist, aber ich habe gerade diese plumpen Dezimal-UCD-Konverter mit fast hundert Bytes gefunden, von denen einige sogar den Laderaum durcheinander bringen oder spezielle fehlerhafte
sed
Versionen erfordern .Für Dezimalstellen zu UCD ich (68 Bytes; früher am besten hier gepostet 87 Bytes)
UCD zu Dezimal ist (auch 66 Bytes; früher am besten hier gepostet 96)
\n
im ersatz ist nicht tragbar. Sie können stattdessen ein anderes Zeichen verwenden und zwei Bytes speichern. Stattdessen benötigen Sie mehr Bytes, um den Anhang zu entfernenP;d
. siehe nächste Bemerkung Wenn Ihr Speicherplatz leer ist, verzichten SieG;s/$/9876543210/
auf eine Byte-Strafe.s/\n.*//
stattdessenP;d
.sed
Versionen könnten Sie jeweils zwei Bytes einsparenquelle
sed
Versionen ausgeführt, die gegen den POSIX-Standard verstoßen.Lesen Sie die gesamte Eingabe auf einmal mit
-z
Häufig müssen Sie den gesamten Eingang auf einmal und nicht nur eine Zeile gleichzeitig bearbeiten. Der
N
Befehl ist dafür nützlich:... aber normalerweise kannst du es überspringen und das benutzen
-z
stattdessen Flagge verwenden.Das
-z
Flag setzt sed\0
anstelle von NUL ( ) als Trennzeichen für\n
die Eingabezeile ein. Wenn Sie also wissen, dass Ihre Eingabe kein Trennzeichen enthält\0
, wird die gesamte Eingabe auf einmal als einzelne „Zeile“ gelesen:Probieren Sie es online!
quelle
Fügen Sie eine neue Zeile in einem Byte hinzu
Der
G
Befehl fügt eine neue Zeile und den Inhalt des Speicherbereichs an den Musterbereich an. Wenn der Speicherbereich also leer ist, geschieht Folgendes:Du kannst das:
Stellen Sie eine neue Zeile in drei Bytes voran
Der
H
Befehl fügt eine neue Zeile und den Inhalt des Pattern-Space an den Hold-Space an undx
tauscht die beiden aus. Wenn Ihr Hold-Space also leer ist, geschieht dies stattdessen folgendermaßen:Du kannst das:
Dies verschmutzt Ihren Laderaum und funktioniert nur einmal. Für zwei weitere Bytes könnten Sie jedoch vor dem Auslagern den Musterbereich leeren, was immer noch eine Einsparung von zwei Bytes bedeutet:
quelle
In sed ist das, was einer Funktion am nächsten kommt, ein Label. Eine Funktion ist nützlich, weil Sie ihren Code mehrmals ausführen können, wodurch viele Bytes gespart werden. In sed müssten Sie jedoch das Rücksendeetikett angeben, und als solches können Sie diese "Funktion" nicht einfach mehrmals im gesamten Code aufrufen, so wie Sie es in anderen Sprachen tun würden.
Die Problemumgehung, die ich verwende, besteht darin, in einen der beiden Speicher ein Flag einzufügen, mit dem das Rückkehretikett ausgewählt wird. Dies funktioniert am besten, wenn der Funktionscode nur einen einzigen Speicherplatz benötigt (den anderen).
Beispiel zeigt, was ich meine: aus einem Projekt von mir genommen, um ein kleines Spiel in sed zu schreiben
Die Bezeichnungen sollten natürlich nur einen Buchstaben lang sein, ich habe zur besseren Erklärung vollständige Namen verwendet.
quelle
Leere reguläre Ausdrücke entsprechen dem zuvor angetroffenen regulären Ausdruck
(Danke an Riley, der dies aus einer anagolischen Einsendung herausgefunden hat )
Hier ist ein Beispiel, in dem wir die Aufgabe haben, 100
@
s in einem leeren Puffer zu erstellen .Die zweite Lösung ist 1 Byte kürzer und verwendet die Tatsache, dass leere reguläre Ausdrücke mit dem zuletzt gefundenen regulären Ausdruck gefüllt werden. Hier war für die zweite Substitution die letzte Regex
.*
, daher wird die leere Regex hier mit gefüllt.*
. Dies funktioniert auch mit regulären Ausdrücken in/conditionals/
.Beachten Sie, dass es sich um den zuvor angetroffenen regulären Ausdruck handelt, sodass auch der folgende funktioniert.
Der leere Regex wird gefüllt,
@*
anstatt$
dass ers/$/@/
nie erreicht wird.quelle
Meist nutzloser Schritt:
Dies wird nur
A
zuB
undy
zuz
(... und-
zu-
;) übersetzen, aber sonst nichtsIch komme gerade zurück:
Sie könnten dies sicherzustellen nutzlos sein wird, für die Probe durch diese Verwendung auf Klein hexadezimalen Werten (mit nur
0
,1
,2
,3
,4
,5
,6
,7
,8
,9
,a
,b
,c
,d
,e
oderf
.)quelle
sed '; ;/s/b;y|A-y|B-z|;s ;s/ //; ; ;' <<<'Hello world'
(Warum wird das Leerzeichen nicht unterdrückt?)