簡體   English   中英

如何通過名稱而不是固定列從類似JSON的文本中提取字段?

[英]How can I extract a field from JSON-like text by name instead of by a fixed column?

我想逐行從文本文件中提取子字符串。 我需要的信息在特定字段下。 例如,我有以下文本:

{name:x, version:1.0, info:"test", ...}
{name:y, version:0.1, info:"test again", ...}
{name:z, version:1.1, info:"test over", ...}

我嘗試使用以下命令提取所有版本:

cut -d',' -f 2 <file name> | cut -d':' -f 2 > <output>

這不是完美的。 這適用於上面的示例,但是如果我輸入以下內容:

{name:x, info: "test", ..., version:1.2, ...}

上面的命令將報告錯誤的版本。 有什么方法可以根據字段名稱而不是按列提取信息?

預期結果:

1.0
0.1
1.1
1.2

使用這個awk

awk -v f='version' -F ' *[{}:=,] *| +' '{for (i=2; i<=NF; i++) if ($(i-1)==f) 
   {print $i; break}}' file
1.0
0.1
1.1
1.2

將GNU grep用於-P (PCRE Regex)和--only-matching選項,您可以執行以下操作:

$ cat file
{name:x, version:1.0, info:"test", ...}
{name:y, version:0.1, info:"test again", ...}
{name:z, version:1.1, info:"test over", ...}
{name:x, info: "test", ..., version=1.2, ...}
$ grep -oP '(?<=version.)[^,}]+' file
1.0
0.1
1.1
1.2

我們使用version后跟. (與任何字符匹配)並在斷言( ?<= )后帶有正向外觀,並將所有內容打印到,

將Grep與PCRE一起使用以提取字段數據

如果您已安裝pcregrep,或者您的grep已使用PCRE支持進行編譯,則可以grep輸入所需的字段。 例如:

# grep with PCRE support
$ grep -Po 'version:\K[^,}]+' /tmp/corpus
1.0
0.1
1.1
1.2

# pcregrep doesn't need the -P flag
$ pcregrep -o 'version:\K[^,}]+' /tmp/corpus
1.0
0.1
1.1
1.2

無論哪種方式,您都可以通過找到版本字段來開始匹配,用\\K丟棄所有消耗的字符,以便匹配僅捕獲字段數據,然后匹配除逗號或右括號以外的任何內容。 -o標志告訴grep僅打印出結果匹配,而不打印整個行。

您的Grep中沒有PCRE? 只需使用Perl

如果您沒有在grep中編譯與Perl兼容的正則表達式(PCRE),那么您仍然應該擁有Perl本身,因為它是Linux Standards Base的一部分。 使用Perl:

# NB: Avoid speed penalty for $& when perl > 5.10.0 && perl < 5.20.0.
# Use $& and remove the /p flag if you don't have (or need) the
# ${^MATCH} variable.
$ perl -ne 'print "${^MATCH}\n" if /version:\K[^,}]+/p' /tmp/corpus
1.0
0.1
1.1
1.2

# Use the $& special variable when ${^MATCH} isn't available, or when
# using a version without the speed penalty.
$ perl -ne 'print "$&\n" if /version:\K[^,}]+/' /tmp/corpus 
1.0
0.1
1.1
1.2

通過sed

$ sed 's/.*version:\([^,}]*\).*/\1/' file
1.0
0.1
1.1
1.2

再次

sed 's/^.*version://; s/[,}].*//' < file

1.0
0.1
1.1
1.2

這個Perl

perl -nE 'say $3 if m/^\s*{ (([^"]|"[^"]*")*)* \bversion\s*:\s* ([\d.]*)/x' 

  • 與引號內的version:2.2 匹配,
  • 匹配oldversion:1.2這樣的字符串

因此對於以下輸入:

{name: a, version: 1.1, info: "the version: 9.1 is better", oldversion: 0.1}
{name: b, version: 1.2, oldversion: 0.2, info: "the version: 9.2 is better"}
{name: c, info: "the version: 9.3 is better", version: 1.3, oldversion: 0.3}
{name: d, info: "the version: 9.4 is better", oldversion: 0.4, version: 1.4}

將打印

1.1
1.2
1.3
1.4
sed 's/.* version://;s/[^0-9.].*//' YourFile

假設版本號僅使用點和數字,而沒有內部值內容version:

這對我有用

[root@giam20 ~]# cut -f2 -d "," sample.txt | cut -f2 -d ":"
1.0
0.1
1.1

暫無
暫無

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

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