¿Qué consejos generales tienes para jugar al golf en sed? Estoy buscando ideas que se puedan aplicar a problemas de código de golf y que también sean al menos algo específicas para sed (por ejemplo, "eliminar comentarios" no es una respuesta).
Por favor, publique un consejo por respuesta.
F
comando nunca funcionó. ¿Alguien sabe por qué?F
funciona en mi GNU sed (prueba de Debian). Solo se imprime-
si se lee desde stdin, por supuesto, pero eso es de esperar. ¿Qué se obtiene a partir desed -e 'F;Q' /etc/hostname
?char 1: unknown command: F
. Tengo que actualizar sed tal vez; ¿Qué versión tienes? ElL
comando tampoco funciona, pero de todos modos es inútil ya que-l n
existe. Todo lo demás mencionado en el sitio de GNU sed funciona.bash, sed and dc
para todos los que quieran hablar y preguntar sobre estos idiomas. ¡Hagamos una comunidad!Respuestas:
Si necesita usar etiquetas, entonces seguramente querrá que los nombres de sus etiquetas sean lo más cortos posible. De hecho, llevado al extremo, incluso puede usar la cadena vacía como nombre de etiqueta:
fuente
:
ahora requiere una etiqueta.La documentación de GNU sed describe el
s
comando como "navaja suiza de sed" . Pero si todo lo que quiere hacer es reemplazar todas las instancias de un personaje con otro, entonces ely
comando es lo que necesita:es un char más corto que:
fuente
y/12/21/
Considere usar una sintaxis de expresiones regulares extendida (en GNU sed). La
-r
opción cuesta un byte en puntuación, pero usarla solo una vez para eliminar las barras invertidas de un par\(...\)
ya se ha pagado por sí misma.fuente
-r
parece sersed
específica de GNU .+
,?
,{}
y|
en partidos de expresiones regulares, ya que no hay barras invertidas son necesarios tampoco.-E
funciona como un alias-r
en muchassed
implementaciones si no recuerdo mal.Al reemplazar repetidamente en un bucle:
Por lo general, no es necesario reemplazarlo globalmente, ya que el bucle eventualmente reemplazará todas las ocurrencias:
Tenga en cuenta también la extensión GNU anterior: una etiqueta puede tener un nombre vacío, ahorrando más bytes preciosos. En otras implementaciones, una etiqueta no puede estar vacía, y saltar sin una etiqueta transfiere el flujo al final del script (es decir, igual que
n
).fuente
:
)No hay aritmética integrada, pero los cálculos se pueden hacer en unario o en un decimal codificado. El siguiente código convierte el decimal a UCD, con x como unidad y 0 como separador de dígitos:
y aquí está la conversión de nuevo a decimal:
Ambos se toman de una respuesta a "Multiplicar dos números sin usar ningún número" .
El unario simple se puede convertir usando este par de bucles de esta respuesta a "{Números rizados};" , donde está la unidad
;
. He usadov
yx
emparejar a Roman para5
y10
;b
proviene de "bis".fuente
/[;v]/!s/\b/0/2
, que debe cambiarse/[;v]/!s:x\+:&0:
para que funcione. Ver aquí .Como se menciona en
man sed
(GNU), puede usar cualquier carácter como delimitador para expresiones regulares utilizando la sintaxisdonde
%
es un marcador de posición para cualquier personaje.Esto es útil para comandos como
que son más cortos como
Lo que se menciona en la sed de GNU Manual , pero no en
man sed
es que se puede cambiar los delimitadores des///
yy///
así.Por ejemplo, el comando
elimina todas las barras del espacio del patrón.
fuente
Si la pregunta no lo prohíbe explícitamente, el consenso para esta meta pregunta es que la entrada numérica puede estar en unario. Esto le ahorra los 86 bytes de decimal a unario según esta respuesta .
fuente
Ampliando esta respuesta de sugerencia , con respecto a las conversiones entre formatos de números unarios decimales y simples, presento los siguientes métodos alternativos, con sus ventajas y desventajas.
De decimal a simple unario: 102 + 1 (indicador r) = 103 bytes. Conté
\t
como una pestaña literal, como 1 byte.Pruébalo en línea!
Ventaja: es 22 bytes más corto y, como extra, funciona con enteros negativos como entrada
Desventaja: sobrescribe el espacio de espera. Sin embargo, dado que es más probable que necesite convertir el entero de entrada justo al comienzo del programa, esta limitación rara vez se siente.
Simple unario a decimal: 102 + 1 (bandera r) = 103 bytes
Pruébalo en línea!
Ventaja: es 14 bytes más corto. Esta vez, ambas versiones de punta funcionan para enteros negativos como entrada.
Desventaja: sobrescribe el espacio de espera
Para un desafío complicado, tendrá que adaptar estos fragmentos para que funcionen con otra información que pueda existir en el espacio del patrón o el espacio de espera, además del número para convertir. El código se puede jugar más, si sabe que solo trabaja con números positivos o que el cero solo no será una entrada / salida válida.
Un ejemplo de dicha respuesta de desafío, donde creé y usé estos fragmentos, es el recíproco de un número (1 / x) .
fuente
s:\n|@$::g
. tio.run/##K05N@f@/2ErX3krNwIpL30G/…-r
, pero con un nuevo consenso, las banderas no cuentan para el bytecount de todos modos, y no/\n/ta
a/\n/t
, ahorra 1 byte para obtener 96Hablemos de los comandos
t
yT
, que aunque se explican en la página del manual, es fácil olvidarse de ellos e introducir errores accidentalmente, especialmente cuando el código se complica.Declaración de la página de manual para
t
:Ejemplo que muestra lo que quiero decir: supongamos que tiene una lista de números y desea contar cuántos negativos hay. Código parcial a continuación:
Se ve bien, pero no lo es. Si el primer número es positivo, ese código seguirá pensando que fue negativo, ya que el salto realizado a través
t
de la primera línea de entrada se realiza independientemente, ¡ya que hubo unas
sustitución exitosa cuando inicializamos el contador! Correcta es:/-/b increment_counter
.Si esto parecía fácil, aún podría ser engañado al hacer múltiples saltos de un lado a otro para simular funciones. En nuestro ejemplo, el
increment_counter
bloque de código seguramente usaría muchoss
comandos. Regresar conb main
podría causar que otra verificación en "main" caiga en la misma trampa. Es por eso que generalmente regreso de los bloques de código cons/.*/&/;t label
. Es feo, pero útil.fuente
En lugar de borrar el espacio del patrón con
s/.*//
, use elz
comando (en minúsculas) si va con GNU sed. Además del recuento de bytes más bajo, tiene la ventaja de que no comenzará el próximo ciclo como lo hace el comandod
, lo que puede ser útil en ciertas situaciones.fuente
.
).Sé que este es un hilo viejo, pero acabo de encontrar esos torpes convertidores decimales a UCD, con casi cien bytes, algunos incluso desordenan el espacio de espera o requieren
sed
versiones especiales defectuosas .Para decimal a UCD utilizo (68 bytes; anteriormente mejor publicado aquí 87 bytes)
UCD a decimal es (también 66 bytes; anteriormente mejor publicado aquí 96)
\n
En el reemplazo no es portátil. En su lugar, puede usar un carácter diferente y guardar dos bytes, pero necesitará más bytes para eliminar el apéndice en lugar deP;d
; Ver siguiente comentario. O, si su espacio de espera está vacío, no tengaG;s/$/9876543210/
penalización de bytes.s/\n.*//
lugar deP;d
.sed
versiones GNU antiguas con erroresfuente
sed
versiones antiguas que violen el estándar POSIX.Lea toda la entrada de una vez con
-z
A menudo necesita operar en toda la entrada a la vez en lugar de una línea a la vez. El
N
comando es útil para eso:... pero generalmente puede omitirlo y usar la
-z
bandera en su lugar.El
-z
indicador hace que sed use NUL (\0
) como su separador de línea de entrada en lugar de\n
, por lo que si sabe que su entrada no contendrá\0
, leerá toda la entrada a la vez como una sola "línea":Pruébalo en línea!
fuente
Agregar una nueva línea en un byte
El
G
comando agrega una nueva línea y el contenido del espacio de espera al espacio del patrón, por lo que si su espacio de espera está vacío, en lugar de esto:Puedes hacerlo:
Anteponer una nueva línea en tres bytes
El
H
comando agrega una nueva línea y el contenido del espacio del patrón al espacio de espera, yx
cambia los dos, por lo que si su espacio de espera está vacío, en lugar de esto:Puedes hacerlo:
Esto contaminará tu espacio de espera, por lo que solo funciona una vez. Sin embargo, para dos bytes más, puede borrar el espacio de su patrón antes de cambiar, lo que sigue siendo un ahorro de dos bytes:
fuente
En sed, lo más parecido a una función que puede tener es una etiqueta. Una función es útil porque puede ejecutar su código varias veces, ahorrando así muchos bytes. Sin embargo, en sed necesitaría especificar la etiqueta de devolución y, como tal, no puede simplemente llamar a esta "función" varias veces a lo largo de su código de la forma en que lo haría en otros idiomas.
La solución alternativa que uso es agregar en una de las dos memorias una bandera, que se usa para seleccionar la etiqueta de devolución. Esto funciona mejor cuando el código de función solo necesita un único espacio de memoria (el otro).
Ejemplo que muestra lo que quiero decir: tomado de un proyecto mío para escribir un pequeño juego en sed
Por supuesto, las etiquetas deben tener una sola letra, utilicé los nombres completos para una mejor explicación.
fuente
Las expresiones regulares vacías son equivalentes a las expresiones regulares encontradas anteriormente
(gracias a Riley por descubrir esto de una presentación de anagol )
Aquí hay un ejemplo donde tenemos la tarea de crear 100
@
s en un búfer vacío.La segunda solución es 1 byte más corta y utiliza el hecho de que las expresiones regulares vacías se completan con la última expresión regular encontrada. Aquí, para la segunda sustitución, la última expresión regular fue
.*
, por lo que la expresión regular vacía aquí se llenará.*
. Esto también funciona con expresiones regulares en/conditionals/
.Tenga en cuenta que es la expresión regular encontrada anteriormente , por lo que lo siguiente también funcionaría.
La expresión regular vacía se llena en
@*
lugar de$
porques/$/@/
nunca se alcanza.fuente
Paso principalmente inútil:
Esto solo se traducirá
A
haciaB
yy
haciaz
(... y-
hacia-
;), pero nada más, así quesolo regresaremos:
Se podría asegurar que esto será inútil, por ejemplo mediante el uso de esta en los valores hexadecimales en minúscula (que contiene sólo
0
,1
,2
,3
,4
,5
,6
,7
,8
,9
,a
,b
,c
,d
,e
of
.)fuente
sed '; ;/s/b;y|A-y|B-z|;s ;s/ //; ; ;' <<<'Hello world'
(¿Por qué esto no suprime el espacio?)