我有一个分配给变量的字符串:
#/bin/bash
fullToken='{"type":"APP","token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs"}'
我只需要在没有引号的情况下提取l0ng_Str1ng.of.d1fF3erent_charAct3rs
并将其分配给另一个变量。
我知道我可以使用awk
,sed
或cut
,但我无法绕过原始字符串中的特殊字符。
提前致谢!
编辑:我没有醒来我应该指定这是JSON。感谢到目前为止的回复。
EDIT2:我正在使用BSD(macOS)
答案 0 :(得分:3)
看起来你有一个JSON字符串。请记住,JSON是无序的,因此如果您下次以不同的顺序输入字符串,则大多数sed,awk,cut解决方案将会失败。
使用JSON解析器是最强大的。
您可以将ruby与其JSON解析器库一起使用:
$ echo "$fullToken" | ruby -r json -e 'p JSON.parse($<.read)["token"];'
"l0ng_Str1ng.of.d1fF3erent_charAct3rs"
或者,如果您不想要引用的字符串(这对Bash很有用):
$ echo "$fullToken" | ruby -r json -e 'puts JSON.parse($<.read)["token"];'
l0ng_Str1ng.of.d1fF3erent_charAct3rs
或jq:
$ echo "$fullToken" | jq '.token'
"l0ng_Str1ng.of.d1fF3erent_charAct3rs"
即使JSON字符串的顺序不同,所有这些解决方案都能正常工作:
$ echo '{"type":"APP","token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs"}' | jq '.token'
"l0ng_Str1ng.of.d1fF3erent_charAct3rs"
$ echo '{"token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs", "type":"APP"}' | jq '.token'
"l0ng_Str1ng.of.d1fF3erent_charAct3rs"
但是知道你应该使用JSON解析器,你也可以在Gnu Grep中使用PCRE看看背后:
$ echo "$fullToken" | grep -oP '(?<="token":)"([^"]*)'
或者在Perl中:
$ echo "$fullToken" | perl -lane 'print $1 if /(?<="token":)"([^"]*)/'
如果字符串的顺序不同,这两种方法也有效。
或者,使用POSIX awk:
$ echo "$fullToken" | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/"token"/){print $(i+1)}}}'
或者,使用POSIX sed,您可以执行以下操作:
$ echo "$fullToken" | sed -E 's/.*"token":"([^"]*).*/\1/'
这些解决方案最强(使用JSON解析器)更脆弱(sed)。但是我在那里的sed解决方案比其他解决方案更好,因为它将支持JSON字符串中的键,值的顺序不同。
Ps:如果你想删除一行中的引号,那对于sed
来说这是一个很好的工作:
$ echo '"quoted string"'
"quoted string"
$ echo '"quoted string"' | sed -E 's/^"(.*)"$/UN\1/'
UNquoted string
答案 1 :(得分:1)
在awk中:
$ awk -v f="$fullToken" '
BEGIN{
while(match(f,/[^:{},]+:[^:{},]+/)) { # search key:value pairs
p=substr(f,RSTART,RLENGTH) # set pair to p
f=substr(f,RSTART+RLENGTH) # remove p from f
split(p,a,":") # split to get key and value
for(i in a) # remove leadin and trailing "
gsub(/^"|"$/,"",a[i])
if(a[1]=="token") { # if key is token
print a[2] # output value
exit # no need to process further
}
}
}'
l0ng_Str1ng.of.d1fF3erent_charAct3rs
l0ng_String
不能包含字符:{}
。
答案 2 :(得分:1)
GNU sed:
fullToken='{"type":"APP","token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs"}'
echo "$fullToken"|sed -r 's/.*"(.*)".*/\1/'
答案 3 :(得分:0)
grep
方法将是,
$ grep -oP '[^"]+(?="[^"]+$)' <<< "$fullToken"
l0ng_Str1ng.of.d1fF3erent_charAct3rs
简要说明,
[^"]+
:grep
会提取非"
模式(?="[^"]+$)
:提取到最后"
您也可以使用sed
方法来执行此操作,
$sed -E 's/.*"([^"]+)"[^"]+$/\1/' <<< "$fullToken"
l0ng_Str1ng.of.d1fF3erent_charAct3rs
答案 4 :(得分:0)
如果字符串的来源是JSON,那么您应该使用特定于JSON的工具。如果没有,那么考虑一下:
$ fullToken='{"type":"APP","token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs"}'
$ echo "$fullToken" | awk -F'"' '{print $8}'
l0ng_Str1ng.of.d1fF3erent_charAct3rs
$ echo "$fullToken" | cut -d'"' -f8
l0ng_Str1ng.of.d1fF3erent_charAct3rs
$ echo "$fullToken" | sed -E 's/.*"([^"]*)"[^"]*$/\1/'
l0ng_Str1ng.of.d1fF3erent_charAct3rs
以上都适用于POSIX shell。如果shell是bash,那么我们可以使用here-string并消除管道。以削减为例:
$ cut -d'"' -f8 <<<"$fullToken"
l0ng_Str1ng.of.d1fF3erent_charAct3rs