Uso de regex ao consultar dados

Expressões regulares (regex) podem ser usadas ao consultar dados do site IBM Cloud Logs para pesquisa de padrões e substituição de strings.

Talvez você queira extrair dados específicos dos seus registros para facilitar a análise e a visualização. Às vezes, você pode querer capturar dados específicos registrados. Em outras ocasiões, talvez seja necessário ocultar dados confidenciais nos registros antes que eles sejam salvos.

Você também pode fazer a correspondência usando um padrão regex em vez de uma pesquisa de texto exata.

O que é regex e como ele funciona?

As expressões regulares, também conhecidas como regex, são uma linguagem específica de domínio (DSL) usada para pesquisas e substituições de padrões.

As informações contidas neste tópico não têm a intenção de fornecer um tutorial educacional completo sobre regex. Se você não estiver familiarizado com regex, talvez queira revisar as informações disponíveis publicamente sobre regex antes de tentar entender os conceitos específicos incluídos aqui.

Conceitos de Regex

Há alguns conceitos básicos que você precisa conhecer para entender os exemplos deste tópico.

Grupo de captura
Regex contido entre parênteses. Os operadores são aplicados ao texto que corresponde à especificação entre parênteses.
Grupo de captura nomeado
Um grupo de captura que está associado a um nome. Os resultados correspondentes podem ser referenciados pelo nome
Classe de caracteres
Um intervalo de caracteres a ser correspondido entre colchetes ( [] ). Um traço pode ser usado como abreviação para listar vários caracteres: [1-5] é o mesmo que [12345].

Quando usar regex

Há ocasiões em que você não precisará de uma expressão regular e poderá simplesmente pesquisar um texto específico. Por exemplo, se você quiser encontrar apenas linhas de registro com o texto user logged in, basta digitar esse texto na pesquisa de registro. Mas se as linhas de registro forem assim: user_32 logged in, não será possível pesquisar o texto exato, pois o ID do usuário é uma variável que muda.

Felizmente, existe um padrão regex para esse caso que utiliza a sequência match anything:

user_d+ logged in

Uso de regex para extrair texto em campos JSON personalizados

Suponha que você tenha um registro não estruturado no seguinte formato:

${logLevel}: World-${worldName}: ${logText}

E você gostaria de converter todas as entradas nesse formato em um objeto JSON no seguinte formato:

{
    "level": `${log-level}`,
    "tag": `World-${worldName}`,
    "text": `${logText}`
}

Você pode usar essa regex para fazer a conversão:

^(?P.*?):s*(?P.*?):

Em que:

  • ^ é o símbolo de início de linha, o que significa que a correspondência precisa começar com o início de uma linha.
  • (?PX) em que X é o que é correspondido e é a sintaxe do grupo de captura nomeado. Essa regex tem três grupos de captura, um para cada chave JSON necessária.
  • s significa "qualquer caractere de espaço em branco".
  • . significa "qualquer um dos caracteres".
  • * significa "0 ou mais correspondências do símbolo ou caractere anterior".
  • .* significa "1 ou mais correspondências do símbolo ou caractere anterior".
  • .*? significa "qualquer caractere, qualquer número de vezes, com a menor quantidade de tokens necessária".

Então, o regex:

^(?P.*?):s*(?P.*?):

Será processado da seguinte forma:

  1. O texto que começa no início de uma linha até o primeiro símbolo : será capturado como o grupo level.

  2. Após qualquer número de espaços em branco, qualquer texto até o próximo símbolo : será capturado como o grupo tag.

  3. O texto do registro é definido automaticamente para o campo text por IBM Cloud Logs, portanto, teremos automaticamente o campo text.

Usando o mesmo regex, o seguinte registro:

"info: World-w-8: generate: new world"

É convertido nesse objeto JSON:

{
   "level": "info",
   "tag": "World-w-8",
   "text": "info: World-w-8: generate: new world"
}

Extração de texto em campos predefinidos

Talvez você queira extrair texto para campos predefinidos. Considere este registro:

"info: World-w-8: generate: new world"

Talvez você queira extrair o texto info para a coluna Severity e o texto World para a coluna Class.

Você pode modificar a regex para definir os nomes corretos dos grupos de captura da seguinte forma:

^(?P.*?):s*(?P.*?)-(?P.*?):

Essa regex formatará o registro para que ele seja exibido como mostrado.

Exemplo de visualização mostrando o registro formatado
Exibição do registro após aplicar a formatação regex

Extração de dados específicos de registros estruturados

Um método semelhante pode ser usado para extrair dados de registros estruturados. A seguir, um exemplo que mostra como extrair dados de um campo JSON específico.

Suponha que você tenha uma linha de registro estruturada semelhante a esta:

{
    "type": `${text}`,
    "log": `${text}`,
    "region": "rg-europe-2"
}

Agora, se o campo region tiver o seguinte formato:

`rg-${"europe"|"asia"|"na"}-${number}`

Queremos extrair a parte que nos informa se a região é europe, asia ou na. O regex para extrair os dados seria:

"region"s*:s*"rg-(?P.*?)-

O grupo de captura nomeado regionName é o que extrai o texto. O nome da região está após o nome da chave region e os caracteres rg-, de acordo com nosso formato. O objetivo dos símbolos s* é fazer com que o regex ainda funcione se houver espaços em branco antes ou depois do símbolo :.

O resultado será semelhante ao seguinte:

{
    "log" : "Bye",
    "regionName" : "na",
    "region" : "rg-na-1",
    "type" : "ltest-w-9"
}

Substituição e remoção de valores

Um dos exemplos mais comuns em que precisamos substituir ou remover valores é a ocultação de dados pessoais. Suponha que você registre números de telefone em algum lugar e não queira que eles sejam salvos em IBM Cloud Logs.

Suponha que tenhamos uma linha de registro não estruturada como esta:

"info: Sender: sendSms: sending sms to phone number +12345678910 to user Andrew"

Você deseja remover o número de telefone e o nome dessa linha. Esse regex corresponderá à linha, começando com "sending sms":

sending sms to phone number +*d+ to user .*

Precisamos escapar do símbolo + com um espaço em branco porque + tem um significado especial na sintaxe regex. Esse significado é "1 ou mais caracteres anteriores".

O símbolo d corresponde a qualquer dígito único. Lembre-se de que o símbolo * significa "0 ou mais caracteres anteriores". Portanto, +*d+ corresponde a um ou mais dígitos que podem ser precedidos por um símbolo + (ou não).

Essa regex substituirá o texto correspondente à regex anterior pelo mesmo texto, mas sem o número de telefone e o nome:

sending sms to phone number * to user *

E aqui está o resultado da aplicação da regra acima:

"info: Sender: sendSms: sending sms to phone number * to user *"

Substituição de valores JSON em registros estruturados

A substituição de valores JSON em logs estruturados é semelhante à substituição de valores em logs não estruturados. A cadeia de caracteres JSON inteira é usada como entrada para a regra Replace.

Usando a seguinte estrutura JSON:

{
   "type": `${text}`,
   "log": `${text}`,
   "region": "rg-europe-2"
}

Suponha que você precise substituir o valor do campo type por outro valor. Veja como você pode corresponder o valor do campo type :

"type"s*:s*".*?"

Lembre-se de que precisamos dos símbolos s* para garantir que a regex funcione se houver espaços em branco antes ou depois do caractere :.

Aqui está a regex para substituir qualquer valor no campo type por newType :

"type":"newType"

Uso de referências anteriores

Suponha que precisemos substituir europe por eu nas cadeias de caracteres no formato west-europe-2. E suponha que precisemos fazer isso não apenas no campo region, mas em qualquer outra parte do registro em que a string seja encontrada. A correspondência desse padrão é feita facilmente com essa regex:

.+?-europe-d+

No entanto, substituir a string usando os métodos que usamos anteriormente pode ser um pouco difícil. Isso ocorre porque precisamos inserir duas cadeias de caracteres antes e depois do texto europe, e essas cadeias podem variar. Para fazer isso, primeiro precisamos capturar as cadeias de caracteres em grupos de captura:

(.+?)-europe-(d+)

Lembre-se de que o símbolo d significa "qualquer dígito" e, junto com +, significa "qualquer dígito uma ou mais vezes". De maneira semelhante, .+ significa qualquer símbolo uma ou mais vezes, mas com a menor quantidade de fichas para fazer a combinação.

Essa regex capturará o texto antes de europe como grupo de captura 1, e o texto depois de europe como grupo de captura 2. A seguinte regex usará referências anteriores para inserir o conteúdo correspondente a esses grupos:

$1-eu-$2

Por exemplo, um registro antes de aplicar nossa regra:

{
    "log" : "Here region is east-europe-1. That's it",
    "type" : "newType",
    "region" : "east-europe-1"
}

E o registro após a aplicação da regra:

{
    "log" : "Here region is east-eu-1. That's it",
    "type" : "newType",
    "region" : "east-eu-1"
}

Acionamento de alertas com regex

Outro caso de uso popular para regex em IBM Cloud Logs é a definição de alertas. A sintaxe de alertas é igual à sintaxe de consulta de registros.

Digamos que queiramos nos alertar em uma linha com o seguinte formato:

`App: init: World-${name}: generation error: ${err}`

E suponha que desejemos receber alertas apenas para os mundos w-1, w-2, w-3 ou w-4. Nosso regex de alerta terá a seguinte aparência:

/text.keyword:/.*World-w-[1-4]: generation error.*//

Lembre-se de que [1-4] corresponde a qualquer caractere único de 1 a 4, e .* corresponde a qualquer caractere, qualquer número de vezes.

Para obter mais informações sobre alertas, consulte: