Eu não consigo compreender o regex… já li vários tutoriais e sites com exemplos e tudo e não consigo fazer algo simples…
tenho que ler um texto e geralmente vem assim, uma pergunta e uma resposta nesse formato:
pergunta
resposta
pergunta
resposta
precisava procurar pela pergunta que é marcada pelo “>” e pegar a resposta
pensei primeiro em verificar se está tendo pergunta, verificando se retornou “>” ai continuar com a leitura
public void validaResposta(String input) {
Pattern pattern;
Matcher matcher;
pattern = Pattern.compile("NAO SEI COMO FAZER", 32);
matcher = pattern.matcher(input);
if (matcher.matches()) {
System.out.println("RESPOSTA: " + matcher);
}
}
A moral do regex é fazer um texto cujos caracteres sejam “genéricos”, de modo a se encaixarem com todas as combinações de textos aceitáveis (e somente com as aceitáveis).
Por exemplo, um possível regex pra ler uma data num formato com 28/05/2014 poderia ser assim: [0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]
Por partes…
[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]
Essa parte em negrito significa: qualquer dígito que vá de 0 até 9.
[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]
Mesma coisa que a anterior.
[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]
Aqui, ele diz: aceitar somente uma barra
E assim sucessivamente.
A tradução para o português seria:
um número, um número, uma barra, um número, um número, uma barra, um número, um número, um número, um número.
É importante frisar que ele aceitaria uma entrada tipo 00/00/0000, ou seja, ele não é um regex muito útil pra validar uma data de verdade
No exemplo que você deu, sobre descobrir se é ou não uma pergunta, eu teria o seguinte raciocínio:
Fazer um regex que aceita o primeiro caracter como sendo um sinal de “maior que” (no caso, o >) e qualquer coisa depois disso.
Você escreve o regex em cima e as opções embaixo. E o resultado vai saindo do lado. Além disso, ele tem uma pequena referência no final da página.
Para esse seu caso você deve reconhecer:
Um sinal de maior ( > ) no início da linha
Qualquer caracter que venha depois disso
Uma quebra de linha
Qualquer caracter que venha até chegar no final da linha
Ficando assim:
1.
"^>"
e 3.
".*?\n"
".*?\n$"
Logo, algo assim resolve:
"^>(.*?)\n(.*?)$"
Os parenteses servem para definir os grupos que você vai selecionar, então o grupo de índice 1 é a pergunta e o grupo de índice 2 é a resposta.
Vale lembrar que o grupo de índice 0 é a regular INTEIRA.
Não conseguiu USAR o site ou não conseguiu fazer a sua regex funcionar?
Você pode fazer isso em 2 passos:
"^Password\\s*OK\\s*\\n((.|\\n)*)"
Depois, você pega o grupo 1 dessa regex e aplica a regular da resposta acima.
Lembre que para o Java, como a regex fica em String, você não pode usar a \ sozinha, tem que ficar sempre 2, assim \.
Então, quando o código for \n, no java vai ficar assim: \n
quando for \s no java fica \s.
Quando você quiser pegar uma aspa dupla ("), você usa UMA barra antes dela, assim:
"minha regex e no meio \" dela tem uma aspa dupla"
No site esqueci de tirar as aspas… eu editei mas acho que vc não leu depois, foi mal por escrever antes de tentar…
Funcionou perfeitamente como vc fez…
só no método que não estou conseguindo separar… como passei o do hardmodel, ele traz certinho o resultado “8” mas no método não sai só o valor, vem todo o escrito junto…
Você quer pegar um Array com a pergunta e password, você quer popular um objeto, você quer devolver só uma String mesmo… Existem algumas coisas erradas ai, mas antes, me explique direitinho o que você precisa fazer com isso:
>daf hardmodel
8
Depois, me explique por que você fez um só para o hardmodel? É só ele que vale ou vc pretende fazer um para cada um (duplicando esse código)?
Quero pegar o resultado de cada pergunta, o resultado vou colocar na tela (com swing no aplicativo) para preencher um campo,
por exemplo,
Hardmodel: [ 8 ]
Version: [ XX ]
eu leio uma porta serial, que me retorna todos esses campos de uma só vez, então vou criar vários métodos para cada item para pegar o valor de cada um.
e para identificar qual campo é o valor, tenho que separar todos e pegar um de cada vez para cada pergunta
entendeu?
assim quero criar métodos para cada pergunta e pegar a resposta e colocar na tela nos seus respectivos campos.
[code] private static final Pattern PATTERN_VALIDA_RESPOSTA = Pattern.compile("^Password\sOK\s\n((.|\n))"); // Cria uma vez só.
private static final Pattern PATTERN_VALIDA_PASSWORD = Pattern.compile("(?<=>)((.?)([0-9]+))", Pattern.DOTALL); // É importante ter esse parametro
public Map<String, String> validaResposta(String input) {
Matcher matcher = PATTERN_VALIDA_RESPOSTA.matcher(input);
if (matcher.matches()) {
String passwords = matcher.group(1); // no grupo 1 temos TUDO que vem depois de Password OK
System.out.println(">>>> Passwords ok: " + passwords);
return buildMap(passwords); // é válida
}
return null; // é inválida
}
private Map<String, String> buildMap(String passwords) {
Map<String, String> map = new HashMap<String, String>();
Matcher matcher = PATTERN_VALIDA_PASSWORD.matcher(passwords);
while (matcher.find()) {
String nome = matcher.group(2);// só o nome;
String password = matcher.group(3);// só o password;
map.put(nome, password); // popula o map.
}
System.out.println(">>>> map ok: " + map);
return map;
}[/code]
O ponto é o seguinte: você usa o find para ir iterando sobre cada pedaço da String (que eu tive que mudar a regex, para atender o caso).
Valeu rafa pela resposta… mas não posso sair do padrão de métodos
O “Dono do sistema” quer que eu faça igual ele fez para outro dispositivo serial… verificando assim, achou a parte do hardmodel? então pega o valor da linha debaixo…
daf hardmodel (procurar por este…)
8 (… e pegar esse valor)
assim em diante… é um cara fechado que acha que só o jeito que ele conhece que é bom… to me matando nesse projeto aqui no trabalho por causa disso
Então está na hora de procurar outro emprego. ¯_( ツ )_/¯
Gente assim só vai fazer você andar para trás. Ele não vai aceitar nada novo/melhor.
Enfim, pode fazer isso, mas vc pode encapsular isso dele. Separe todo código repetido em um método e chame esse método. Não é bonito, mas é muito, mas muito “menos feio”.
Não sei bem… porque mal vi regex… Eu peguei isso de gaiato…
Eu queria reformular tudo isso… mas como mexe com receber dados da porta serial, não quis mexer muito por falta de conhecimento, então nem sei como melhorar…
Vou tentar mostrar para eles que o que vc fez é o melhor jeito…
Você vai saber qual o valor de cada propriedade e ainda vai ver que elas seguem as potências de base 2.
Ou seja: 2^0, 2^1, 2^2, 2^3, etc…
Com isso você consegue, por qualquer número positivo informado, saber quais opções você escolheu:
2^0=1
2^1=2
2^2=4
2^3=8
Se eu informar o número 5, significa que eu escolhi o 1 e o 4.
Se eu informar o número 7, significa que eu escolhi o 1, o 2 e o 4.
Se eu informar o número 4, significa que eu escolhi o 4.
etc…
Assim você descobre como tornar seu código melhor…
Pq o matches é quando a regex pega a linha toda (ou a string toda, caso só tenha uma linha).
Ou seja, ele basicamente engloba o seu regex entre o ^ (início de linha) e o $ (fim de linha).
Vamos supor:
String test1 = "ab cd ef gh";
Matcher m1 = Pattern.compile("[cd]").match(test1); // Pattern que procura por "c" OU "d"
// System.out.println(m1.matches()); // False pois a string começa com "a" e termina com "h"
// System.out.println(m1.find()); // True pois na string contém "c" ou "d"
while (m1.find())
System.out.println(m1.group(1)); // primeiro printa "c" e depois printa "d"
Para que isso funcione com o matches, você precisaria pegar a linha inteira com o seu Pattern:
String test1 = "ab cd ef gh";
Matcher m1 = Pattern.compile("^[a].*?([c][d]).*$").match(test1); // Pattern que procura por "c" seguido de "d" depois de ter começado com a letra "a"
// System.out.println(m1.matches()); // True pois a string começa com "a" e no meio dela encontramos um "c" seguido de um "d"
if (m1.matches())
System.out.println(m1.group(1)); // printa "cd"
Mas no meu caso, que não sei bem como começa e muito menos como termina
Dados:
Password OK
daf hardmodel
8
daf hardversion
0
daf hardtype
7
daf bootversion
1
daf appversion
81280001
param get cmid
Not found
param get devid
devid (u32) = 8012405
param get keyfobid1
keyfobid1 (u32) = 4294967048
param get keyfobid2
keyfobid2 (u32) = 11
pensei que dava para pegar um texto, selecionar a parte dele com o pattern.compile e pegar o valor depois dele… por isso pensei em criar métodos para cada item…
quero saber do hardmodel… procuro pela palavra hardmodel e pego o valor depois dele ( 8 ) e termino quando encontrar um “>”