Eu gostaria de ter um script simples que me permitisse passar qualquer texto e extraísse um valor para uma chave da string.
Eu gostaria que isso fosse flexível e aceitasse entrada XML ou JSON e até mesmo entradas mal formadas, como texto de um log.
por exemplo, dada qualquer uma das seguintes entradas, deve ser capaz de extrair o valor da test
chave.
por exemplo
$ echo "test:5 hi there" | extract_key_value test
deve resultar em
5
Observe que eu não me importo com o que está escrito, então node, ruby, etc está bem para mim, mas a portabilidade (Linux/osx) é boa ;-)
entrada1
this is test:5 i saw a value
entrada2
this is test:'another value' i saw a value
entrada3
this is test=5 i saw a value
entrada 4
test='a string value here'
entrada 5
my data
on line 2 test='a string value here'
more data
Minha dica rápida para isso é o seguinte, que acho que pode ser muito melhorado e parece que deve ser resolvido em algum lugar!
extract_key_value
#!/usr/bin/env bash
function show_help()
{
IT=$(cat <<EOF
Helps you extract a key value from a string, typically a log msg
usage: key {keyBeginDelim} {keyEndDelim}
e.g. given "asd f asdf asdf test=easy asdf me=you" as input
extract_key_value test
=> returns easy
EOF
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
INPUT=$(cat -)
KEY="$1"
function getVal()
{
DELIM1="$1"
DELIM2="$2"
echo "$INPUT" | awk -F "$DELIM1" '{print $2}' | awk -F "$DELIM2" '{print $1}'
}
# Try whatever the user passed in or defaults for delims
if [ -n "$2" ]
then
IT=$(getVal "$2" "$3")
fi
# Try other use cases
if [ -z "$IT" ]
then
IT=$(getVal "$KEY:'" "'")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY='" "'")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY=\"" "\"")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY:\"" "\"")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY:" " ")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY=" " ")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY=" ";")
fi
if [ -z "$IT" ]
then
IT=$(getVal "$KEY:" ";")
fi
echo "$IT"
Com
pcregrep
:-M
: correspondência de várias linhas (para permitirtest:'foo\nbar'
...)-o1
: saída do texto correspondente ao primeiro grupo de captura (veja abaixo sobre a redefinição do branch ).(?sx)
: habilite os
sinalizador (faça.
corresponder também os caracteres de nova linha) ex
o sinalizador (permita essa multilinha com formato de comentário)\Q$1\E
o conteúdo de$1
(o primeiro argumento para a função) deve ser tomado literalmente. Isso pressupõe que não se contém\E
. Em shells do tipo ksh93 comobash
, você pode substituir$1
por${1//\\E/\\E\\\\E\\Q}
para contornar isso.(?|.(.).|.(.).)
redefinição de ramal. A numeração do grupo de captura inicia em 1 após cada|
, portanto-o1
, retornará o primeiro grupo de captura que corresponder em qualquer uma das alternâncias.'.*?'
..*?
é a variante não gananciosa de.*
, portanto'.*'
, corresponderá de'
para o primeiro'
depois disso.\s
: qualquer caractere de espaço em branco.Isso não tenta resolver casos de canto como as
\x
codificações em json, a incorporação de aspas entre aspas (o que é feito de maneira diferente dependendo do idioma). Ele não permite espaços em branco em nenhum dos lados do:
ou=
. Todos esses podem ser abordados, se necessário. Isso dependerá do tipo de entrada exata que você está tentando processar.Um exemplo com grep: