簡體   English   中英

使用awk從更大的JSON字符串中提取令牌

[英]Using awk to extract a token from a larger JSON string

我有一個分配給變量的字符串:

#/bin/bash

fullToken='{"type":"APP","token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs"}'

我只需要提取不帶引號的l0ng_Str1ng.of.d1fF3erent_charAct3rs並將其分配給另一個變量。

我知道我可以使用awksedcut但是我很難避開原始字符串中的特殊字符。

提前致謝!

編輯:我不醒,我應該指定這是JSON。 到目前為止,感謝您的答復。

EDIT2:我正在使用BSD(macOS)

看起來您那里有一個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字符串中的值以不同的順序排列。


附:如果您想刪除一行中的引號,那么對於sed來說是個好工作:

$ echo '"quoted string"' 
"quoted string"
$ echo '"quoted string"' | sed -E 's/^"(.*)"$/UN\1/'
UNquoted string

在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不能包含字符:{}

GNU sed:

fullToken='{"type":"APP","token":"l0ng_Str1ng.of.d1fF3erent_charAct3rs"}'
echo "$fullToken"|sed -r 's/.*"(.*)".*/\1/'

grep方法應該是

$ grep -oP '[^"]+(?="[^"]+$)' <<< "$fullToken"
l0ng_Str1ng.of.d1fF3erent_charAct3rs

簡要說明,

  • [^"]+grep將提取非"模式
  • (?="[^"]+$) :提取直到最后一個"

您也可以使用sed方法來做到這一點,

$sed -E 's/.*"([^"]+)"[^"]+$/\1/' <<< "$fullToken"
l0ng_Str1ng.of.d1fF3erent_charAct3rs

如果字符串的來源是JSON,則應使用特定於JSON的工具。 如果沒有,請考慮:

使用awk

$ 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

使用sed

$ echo "$fullToken" | sed -E 's/.*"([^"]*)"[^"]*$/\1/'
l0ng_Str1ng.of.d1fF3erent_charAct3rs

使用bash和以上之一

以上所有功能都適用於POSIX shell。 如果外殼是bash,則可以使用here-string並消除管道。 以切割為例:

$ cut -d'"' -f8 <<<"$fullToken"
l0ng_Str1ng.of.d1fF3erent_charAct3rs

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM