나는 어떤 텍스트라도 전달하고 문자열에서 키 값을 추출할 수 있는 간단한 스크립트를 원합니다.
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"
답변1
그리고 pcregrep
:
extract_key_value() {
pcregrep -Mo1 "(?sx)
(?:
\Q$1\E # key literally
| \"\Q$1\E\" # same in double quotes
| '\Q$1\E' # same in single quotes
)
[=:]
(?| # branch reset
'(.*?)'
| \"(.*?)\"
| ([^\"'\s]+)
)"
}
-M
:여러 줄 일치(test:'foo\nbar'
... 허용)-o1
: 첫 번째 캡처 그룹과 일치하는 텍스트를 출력합니다(아래 참조).분기 재설정).(?sx)
: 활성화s
플래그(.
새 줄에도 일치) 및x
플래그(주석 형식이 있는 여러 줄 허용)\Q$1\E
(함수의 첫 번째 매개변수)는$1
문자 그대로 받아들여야 합니다. 그 자체를 포함하지 않는다고 가정합니다\E
. ksh93과 유사한 셸에서는 교체를 통해 이 문제를 해결할bash
수 있습니다 .$1
${1//\\E/\\E\\\\E\\Q}
(?|.(.).|.(.).)
지점 재설정. 캡처 그룹의 번호는 각 이후 1부터 시작하므로|
교대-o1
로 일치하는 첫 번째 캡처 그룹이 반환됩니다.'.*?'
..*?
예, 탐욕스럽지 않은 변형.*
이므로 to 이후의 첫 번째 변형'.*'
과 일치합니다 .'
'
\s
: 모든 공백 문자.
\x
이것은 json 인코딩, 따옴표 안에 따옴표 삽입(언어에 따라 다름)과 같은 특수한 경우를 해결하려고 시도하지 않습니다 . 양쪽에 :
공백을 허용하지 않습니다 =
. 필요한 경우 이 모든 문제를 해결할 수 있습니다. 이는 처리하려는 입력의 정확한 유형에 따라 달라집니다.
답변2
grep의 예:
function extract_key_value() {
egrep -o "$1[:=]['\"[:alnum:]]+" | egrep -o "['\"[:alnum:]]+$" | egrep -o "[[:alnum:]]+"
}
echo -e "on line 1\ntest:123 asasas\non line 3\ntest='abc'\non line 5" | extract_key_value test