我想要一个简单的脚本,让我可以将任何文本传递给它,并从字符串中提取一个键的值。
我希望它灵活,并接受 XML 或 JSON 输入,甚至是格式不正确的输入,例如日志中的文本。
例如,给定以下任何输入,它应该能够提取test
键的值。
例如
$ echo "test:5 hi there" | extract_key_value test
应该导致
5
请注意,我不在乎它是用什么写的,所以 node、ruby 等对我来说很好,但是可移植性(Linux/osx)很好;-)
输入1
this is test:5 i saw a value
输入2
this is test:'another value' i saw a value
输入3
this is test=5 i saw a value
输入4
test='a string value here'
输入5
my data
on line 2 test='a string value here'
more data
我对此的快速破解如下,我觉得可以大大改进,感觉应该在某个地方解决!
提取键值
#!/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"
与
pcregrep
:-M
: 多行匹配(允许test:'foo\nbar'
...)-o1
:输出与第一个捕获组匹配的文本(见下文关于分支重置)。(?sx)
:启用s
标志(也.
匹配换行符)和x
标志(允许带有注释格式的多行)\Q$1\E
(函数的第一个参数)的内容$1
应按字面意思理解。假设它不包含\E
自身。在类似 ksh93 的 shellbash
中,您可以替换$1
为${1//\\E/\\E\\\\E\\Q}
来解决这个问题。(?|.(.).|.(.).)
分支重置。捕获组的编号在 each 之后从 1 开始|
,因此-o1
将返回在任何交替中匹配的第一个捕获组。'.*?'
..*?
是 的非贪婪变体.*
,因此'.*'
将匹配之后'
的第一个'
。\s
: 任何空白字符。这并没有尝试解决像
\x
json 中的编码这样的极端情况,在引号中嵌入引号(根据语言的不同,这样做的方式不同)。它不允许在:
or的任何一侧有空格=
。如果需要,所有这些都可以解决。这将取决于您尝试处理的确切输入的类型。使用 grep 的示例: