[英]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
后跟.
(與任何字符匹配)並在斷言( ?<=
)后帶有正向外觀,並將所有內容打印到,
。
如果您已安裝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中編譯與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.