🤔 Para Refletir :
"Um artista precisa somente de duas coisas: Honestidade e fé."
- Carlos Davilla

Expressões regulares de string em Ruby (gsub!)

Estado
Tópico fechado. Não é possível fazer postagens nela.

Pretty-Belle

Cidadão
Membro
Membro
Juntou-se
18 de Junho de 2015
Postagens
155
Bravecoins
112
Vim encher de novo o saco de vocês :B
Tava fuçando Window_Base para ver como fazem para converter chars especiais em rich text. Isso porque eu queria criar umas propriedades extras nos eventos, usando o nome deles para extrair tais propriedades. Por exemplo, se o nome dele for <bla 3><tcha 34, 29>, eu queria pode extrair esse valores de alguma forma do event.name
Enfim, acho que o que eu quero é o gsub!, já que é o que tá lá Window_Base. Me deparei com uns treco desse:
Código:
result.gsub!(/\eV\[(\d+)\]/i) { $game_variables[$1.to_i] }
Só que num entendi foi lhufas .______. Alguém sabe o que diabos isso quer dizer e como esse tal gsub! funciona? Eu tentei procurar na internet mas não ajudou muito D: Por que que tem esse monte de barra e contra-barra aí no meio? Para fazer isso que eu mencionei (extrair um número dentro de um padrão de string), como eu teria que usar isso?
Thanks ~
 
Não vou conseguir te dar alguma resposta conclusiva quanto a isso, Regex é uma coisa que não tive taaanto contato. O que devo concordar é Regex a primeira vista parece uma coisa bizarra.

Vou explicar alguns detalhes.

Específico de Ruby: Em Ruby, quando você encontra /texto/, significa que "texto" é uma regex. Ou seja, o que você deve "interpretar" da sua regex é só:
Código:
\eV\[(\d+)\]

Outro detalhe é o "i" ao final da barra. Isso indica que o resultado final vai ser um inteiro.

Expressões regulares são usadas no RPG Maker para encontrar padrões e etc.
Exemplo, se você tem a string: "aqui há uma <tag>excesso>, viu?" e você quiser tudo que estiver entre <>, você pode usar as expressões regulares:

1:
Código:
<(.*)>
2:
Código:
<(.*?)>

Com a 1ª, o resultado encontrado será tudo que estiver desde após o primeiro "<" até antes da última ocorrência de um ">" (por conta do ".*"), ou seja, o resultado será "tag>excesso". Esse modo se chama "guloso" (no inglês chamam de greedy, que seria "ganancioso", mas enfim, nomenclaturas...). Na 2ª há o marcador "não-guloso" (lazy), o que significa que o resultado será tudo que estiver desde após o primeiro "<" até antes da primeira ocorrência de um ">", ou seja, o resultado será "tag".

Indo por partes...

\e: Infelizmente não achei nada documentado de para quê serve esse operador =T mas provável que seja para dizer "tanto faz se o próximo caractere for maiúsculo ou não", você pode dar um "\v" e um "\V" para testar. Nos parsers online vi que significa o código ASCII relativo ao comando "esc", o que não faz sentido aí. Digitou-o sem querer talvez? Não chequei se está assim no padrão do RPG Maker, mas enfim...

V: é simplesmente a letra V maiúscula.

\[ e \]: como "[" e "]" são identificadores com suas interpretações próprias dentro de Regex (assim como o "?"), e no caso o RPG Maker espera encontrar literalmente "\V[###]", coloca-se uma "\" antes de "[" ou "]" (ou outros caracteres especiais, como ".", "*", "?", etc...) para dizer: "é literalmente um '[', e não o comando dentro da regex".

( e ): indicam que o que estiver dentro deles é um "grupo de captura", ou seja, dentro desse padrão todo da Regex que você está verificando, onde está o valor que você quer capturar (ou seja, dentro de \V[12], você quer que retorne o 12, ou seja, o 12 deve ser reconhecido como "grupo de captura").

\d: indica qualquer número decimal (ou seja, qualquer número de 0-9).

+: indica que deve ser encontrado um ou mais ocorrências do que estiver antes do +. No caso, \d+ quer dizer "quantos números for capaz de encontrar" (e.g.: "\d" captura 2, mas não captura 12, enquanto "\d+" captura tanto 2 quanto 12).

Ou seja, a regex (note que substituí o "e" por um "\"):

Código:
/\\V\[(\d+)\]/i

Quer dizer: "Encontre todo padrão '\V[###]', em que # é um número decimal (0 a 9) de quantas casas forem possíveis, e retorne o #. No fim, Ruby deve interpretar # como um Integer (denotado pelo 'i' no final)".

No caso, <string>.gsub!(<regex>) invoca um bloco (ou seja, código dentro de {}) para cada resultado (prefiro chamar de ocorrência) que ele encontrar a partir da <regex> atuando na <string>. Cada grupo de captura da regex (ou seja, do padrão! Lembrando que você pode ter mais de um grupo de captura numa mesma regex) é enumerada da forma: $1 é a primeira ocorrência, $2 é a segunda, $3 é a terceira...

Ou seja, a regex:

Código:
\[(\d+);(\d+);(\d+)\]

Possui 3 grupos de captura (todos números inteiros de quantas casas forem necessárias. Essa regex atuando na string:

Código:
minha cor RGB é [255;128;48]

Retorna os grupos:

Código:
$1 = 255
$2 = 128
$3 = 48

(Verifique aqui: https://regex101.com/r/uY3jW8/2)

Como na regex que você postou só tem um grupo de captura (ou seja, "(<algo>)" só aparece uma única vez), então é usado apenas um $1.



Adicionais: Ainda sobre o exemplo do RGB ali, se você seguir o link que deixei e tentar colocar espaços entre os ";", note que os números já não serão capturados. I.e. (perceba os " " após cada ";"):

Código:
Minha cor RGB é: [255; 128; 48].

Isso ocorre porque a regex é bastante literal. Para corrigir isso você pode adicionar " *" após cada ";" na regex:

Código:
\[(\d+); *(\d+); *(\d+)\]

Assim o usuário pode colocar quantos " " ele quiser após cada ";" que não irá causar problemas no resultado ;) No caso, se fosse colocado apenas (só com espaços, sem o *):

Código:
\[(\d+); (\d+); (\d+)\]

O usuário deverá colocar apenas 1 único " " após cada ";". Porém com o operador * ele pode colocar 0 ou infinitos espaços que não terá problema (i.e. tanto "[1;1;1]" quanto "[1;      1;    1]" serão reconhecidos). Ele funciona igual ao "+" que tinha depois dos \d, porém o + significa 1 até infinito (ou seja, no mínimo deve ter 1 daquele caractere ali), e o * significa 0 a infinito.

Verifique em: https://regex101.com/r/uY3jW8/3

(OBS: use e abuse desse regex101, diria que é bom para testar coisas de regex ;D De preferência selecione "Python" no menu à esquerda, que é mais próxima de Ruby).

Enfim, fica de exercício tentar montar sua regex, mas veja que fará uso do + e do * nela ;)

Se quiser postá-la na resposta (ou caso lockem o tópico se a dúvida for sanada) e verificar possíveis problemas, só avisar. A partir daí será mais complicado (que vem a parte de fazer isso funcionar no RPG Maker).

E antes que eu esqueça, note que ".gsub!" tem o "!". Essa marcação em Ruby é um padrão utilizado pelos rubistas para quando o método é "destrutivo". Ou seja, quando você chama "variavel.metodo!", após a realização do método a variável "variavel" é alterada. No caso do "gsub!" ele elimina as partes que ele reconheceu da string, i.e.:

Código:
var = "Meu RGB é: [255;128;48]. Legal né?"
var.gsub!(/\[(\d*); *(\d*); *(\d+)\]/i) {
  msgbox("sua cor é [#{$1}; #{$2}; #{$3}].")
} # => "sua cor é [255; 128; 48]"
msgbox var # => "Meu RGB é: . Legal né?" (o padrão foi removido, mesmo eu não fazendo var = algo).

Isso nesse caso seria bom para que você não acabe errando o regex pegando "regex já reconhecidos".

EE por último EDIT desta noite: http://ruby-doc.org/core-2.1.1/Regexp.html pode ser útil
 
Mds, cê é um anjo ;-;
Eu não conhecia esse termo "regex" (ou até já tinha visto, mas deixei passar xD). Vou olhar mais a fundo os link que você passou, mas só a resposta já esclareceu bastante coisa. Thank you <33
 
Estado
Tópico fechado. Não é possível fazer postagens nela.
Voltar
Topo Inferior