Que dicas gerais você tem para jogar golfe no sed? Estou procurando idéias que possam ser aplicadas a problemas de código-golfe e que também sejam pelo menos um pouco específicas para sed (por exemplo, "remover comentários" não é uma resposta).
Poste uma dica por resposta.
F
comando nunca funcionou. Alguem sabe por quê?F
trabalha no meu GNU sed (teste Debian). Apenas imprime-
se estiver lendo a partir de stdin, é claro, mas isso é esperado. Do que você ganhased -e 'F;Q' /etc/hostname
?char 1: unknown command: F
. Eu tenho que atualizar o sed talvez; Que versão você tem? OL
comando também não funciona, mas é inútil de qualquer maneira, já que-l n
existe. Tudo o mais mencionado no site do GNU sed funciona.bash, sed and dc
para todos que querem conversar e perguntar sobre esses idiomas. Vamos fazer uma comunidade!Respostas:
Se você precisar usar rótulos , com certeza desejará que seus nomes sejam os mais curtos possível. De fato, levado ao extremo, você pode até usar a string vazia como um nome de rótulo:
fonte
:
agora requer um rótulo.A documentação do GNU sed descreve o
s
comando como "canivete suíço do sed" . Mas se tudo o que você deseja fazer é substituir todas as instâncias de um caractere por outro, oy
comando é o que você precisa:é um caractere menor que:
fonte
y/12/21/
Considere usar a sintaxe regex estendida (no GNU sed). A
-r
opção custa um byte na pontuação, mas usá-lo apenas uma vez para eliminar as barras invertidas de um par de\(...\)
já se pagou.fonte
-r
parece sersed
específica do GNU .+
,?
,{}
e|
em partidas regex, uma vez que não barras invertidas são necessários também.-E
funciona como um alias para-r
em muitassed
implementações, se bem me lembro.Ao substituir repetidamente em um loop:
geralmente não é necessário substituir globalmente, pois o loop eventualmente substituirá todas as ocorrências:
Observe também a extensão GNU acima: um rótulo pode ter um nome vazio, economizando mais bytes preciosos. Em outras implementações, um rótulo não pode estar vazio, e saltar sem um rótulo transfere o fluxo para o final do script (ou seja, o mesmo que
n
).fonte
:
)Não há aritmética embutida, mas os cálculos podem ser feitos em decimal unário ou em código unário. O código a seguir converte decimal em UCD, com x como a unidade e 0 como o separador de dígitos:
e aqui está a conversão de volta para decimal:
Ambos são retirados de uma resposta para "Multiplique dois números sem usar nenhum número" .
Unário antigo simples pode ser convertido usando este par de loops desta resposta para "{Números Curly};" , onde está a unidade
;
. Eu useiv
ex
para combinar Roman para5
e10
;b
vem de "bis".fonte
/[;v]/!s/\b/0/2
, que precisa ser alterada/[;v]/!s:x\+:&0:
para que funcione. Veja aqui .Conforme mencionado em
man sed
(GNU), você pode usar qualquer caractere como delimitador para expressões regulares usando a sintaxeonde
%
é um espaço reservado para qualquer caractere.Isso é útil para comandos como
que são mais curtos quanto
O que é mencionado no manual do GNU sed, mas não no,
man sed
é que você pode alterar os delimitadoress///
ey///
também.Por exemplo, o comando
remove todas as barras do espaço do padrão.
fonte
Se não for explicitamente banido pela pergunta, o consenso para essa meta questão é que a entrada numérica pode ser unária. Isso economiza os 86 bytes de decimal para unário, de acordo com esta resposta .
fonte
Expandindo a resposta desta dica , em relação às conversões entre os formatos de número decimal e simples, apresentamos os seguintes métodos alternativos, com suas vantagens e desvantagens.
Decimal para unário simples: 102 + 1 (sinalizador r) = 103 bytes. Eu contei
\t
como uma guia literal, como 1 byte.Experimente online!
Vantagem: é 22 bytes mais curto e, como extra, funciona com números inteiros negativos como entrada
Desvantagem: substitui o espaço de espera. No entanto, como é mais provável que você precise converter o número inteiro de entrada logo no início do programa, essa limitação raramente é sentida.
Simples unário ao decimal: 102 + 1 (sinalizador r) = 103 bytes
Experimente online!
Vantagem: é 14 bytes mais curto. Desta vez, ambas as versões de ponta funcionam para números inteiros negativos como entrada.
Desvantagem: substitui o espaço de espera
Para um desafio complicado, você precisará adaptar esses trechos para trabalhar com outras informações que possam existir no espaço padrão ou manter espaço, além do número a ser convertido. O código pode ser mais golfado, se você souber que trabalha apenas com números positivos ou que apenas o zero não será uma entrada / saída válida.
Um exemplo dessa resposta de desafio, onde eu criei e usei esses trechos, é o Recíproco de um número (1 / x) .
fonte
s:\n|@$::g
. tio.run/##K05N@f@/2ErX3krNwIpL30G/…-r
, mas com novo consenso, os sinalizadores não contam para o número de bytes de qualquer maneira e não atrapalham o espaço de espera)/\n/ta
de/\n/t
, você economiza 1 byte para obter 96Vamos falar sobre os comandos
t
eT
, que, embora sejam explicados na página de manual, é fácil esquecê-lo e introduzir bugs acidentalmente, especialmente quando o código fica complicado.Declaração da página de manual para
t
:Exemplo mostrando o que quero dizer: digamos que você tenha uma lista de números e que deseja contar quantos negativos existem. Código parcial abaixo:
Parece ok, mas não está. Se o primeiro número for positivo, esse código ainda achará negativo, porque o salto realizado pela
t
primeira linha de entrada é realizado independentemente, pois houve umas
substituição bem-sucedida quando inicializamos o contador! Correta é:/-/b increment_counter
.Se isso parecesse fácil, você ainda poderia ser enganado ao fazer vários saltos para frente e para trás para simular funções. No nosso exemplo, o
increment_counter
bloco de código com certeza usaria muitoss
comandos. Retornar comb main
pode fazer com que outro check-in "main" caia na mesma armadilha. É por isso que geralmente retorno de blocos de código coms/.*/&/;t label
. É feio, mas útil.fonte
Em vez de limpar o espaço do padrão
s/.*//
, use oz
comando (minúsculo) se você for com o GNU sed. Além da contagem de bytes mais baixos, tem a vantagem de não iniciar o próximo ciclo como o comandod
, o que pode ser útil em determinadas situações.fonte
.
).Sei que esse é um encadeamento antigo, mas acabei de encontrar os conversores desajeitados de decimal para UCD, com quase cem bytes, alguns até atrapalhando o espaço de espera ou exigindo
sed
versões especiais com defeito .Para decimal em UCD eu uso (68 bytes; o melhor foi postado aqui 87 bytes)
UCD para decimal é (também 66 bytes; o melhor foi postado aqui 96)
\n
na substituição não é portátil. Você pode usar um caractere diferente e salvar dois bytes, mas precisará de mais bytes para remover o apêndice em vez deP;d
; veja a próxima observação. Ou, se seu espaço de espera estiver vazio, façaG;s/$/9876543210/
sem penalidade de bytes.s/\n.*//
vez deP;d
.sed
versõesfonte
sed
versões antigas que violam o padrão POSIX.Leia toda a entrada de uma só vez com
-z
Geralmente, você precisa operar toda a entrada de uma só vez, em vez de uma linha de cada vez. O
N
comando é útil para isso:... mas geralmente você pode pular e usar o
-z
bandeira.O
-z
sinalizador faz com que o sed use NUL (\0
) como seu separador de linhas de entrada em vez de\n
, portanto, se você souber que sua entrada não conterá\0
, ela lerá todas as entradas de uma só vez como uma única “linha”:Experimente online!
fonte
Anexar uma nova linha em um byte
O
G
comando anexa uma nova linha e o conteúdo do espaço de espera ao espaço do padrão; portanto, se o espaço de espera estiver vazio, em vez disso:Você consegue fazer isso:
Anexar uma nova linha em três bytes
O
H
comando anexa uma nova linha e o conteúdo do espaço do padrão ao espaço de espera ex
troca os dois; portanto, se o espaço de espera estiver vazio, em vez disso:Você consegue fazer isso:
Isso poluirá seu espaço de espera, portanto, só funciona uma vez. Porém, para mais dois bytes, você pode limpar o espaço do padrão antes de trocar, o que ainda economiza dois bytes:
fonte
No sed, a coisa mais próxima de uma função que você pode ter é um rótulo. Uma função é útil porque você pode executar seu código várias vezes, economizando muitos bytes. No sed, no entanto, você precisaria especificar o rótulo de retorno e, como tal, não pode simplesmente chamar essa "função" várias vezes em todo o código da maneira que faria em outros idiomas.
A solução alternativa usada é adicionar em uma das duas memórias um sinalizador, usado para selecionar o rótulo de retorno. Isso funciona melhor quando o código de função precisa apenas de um único espaço de memória (o outro).
Exemplo mostrando o que eu quero dizer: retirado de um projeto meu para escrever um pequeno jogo em sed
É claro que os rótulos devem ter apenas uma letra, e usei nomes completos para uma melhor explicação.
fonte
Regexes vazias são equivalentes à regex encontrada anteriormente
(obrigado a Riley por descobrir isso a partir de um envio de anagol )
Aqui está um exemplo em que temos a tarefa de criar 100
@
s em um buffer vazio.A segunda solução é 1 byte menor e usa o fato de que expressões regulares vazias são preenchidas com a última expressão regular encontrada. Aqui, para a segunda substituição, o último regex foi
.*
, portanto, o regex vazio aqui será preenchido.*
. Isso também funciona com expressões regulares em/conditionals/
.Observe que é o regex encontrado anteriormente , portanto, o seguinte também funcionaria.
A regex vazia é preenchida em
@*
vez de$
porques/$/@/
nunca é alcançada.fonte
Passo principalmente inútil:
Isso só será traduzido
A
paraB
ey
paraz
(... e-
para-
;), mas nada mais, entãoretornará apenas:
Pode-se assegurar que esta vai ser inútil, por exemplo, utilizando esta em valores hexadecimais minúsculas (contendo apenas
0
,1
,2
,3
,4
,5
,6
,7
,8
,9
,a
,b
,c
,d
,e
ouf
.)fonte
sed '; ;/s/b;y|A-y|B-z|;s ;s/ //; ; ;' <<<'Hello world'
(Por que isso não suprimir o espaço?)