我有一个1,00,000行的JSON文本文件。手动提取不公平。我编写了一个Perl程序来读取文件的每一行,满足我的需求。
这是一个示例文本文件
"key": "Programming",
"doc_count": 1
"key": "Base",
"doc_count": 1,
"key": "Experience",
"doc_count": 1
"key": "Electrophoresis",
"doc_count": 1
我想单独使用双括号分隔键值,例如编程,基础,经验和电泳。
这是我尝试过的Perl代码:
use strict;
use warnings;
my $file = $ARGV[0];
open my $info, $file or die "Could not open $file: $!";
while ( my $line = <$info> ) {
if ( $line =~ /"key(.*)",/ ) {
print $1;
print "\n";
}
}
close $info;
通过使用它,我得到了这个输出
": "Programming
": "Base
": "Experience
": "Electrophoresis
我不想要领先的冒号和空间。
我试过了$line =~ /"key: "(.*)",/
。但它没有用。该命令执行但没有输出,也没有错误症状。
G:\ExtractKeyValue_Regex>perl ExtractKeyValue.pl Sample.txt > Output_Sample.txt
G:\ExtractKeyValue_Regex>
输出应该是,
Programming
Base
Experience
Electrophoresis
我无法弄清楚为什么冒号:
以及空格和双引号"
未被模式跟踪。
答案 0 :(得分:5)
您显示的所有线条都是
my $key_assoc = $line =~ /: "([^"]+)/;
print "$key_assoc\n" if $key_assoc;
或者您可以输入"key"
字符串和",
以获得额外保证和格式检查
if ($line =~ /"key": "([^"]+)",/) {
# ...
}
请注意,如果有空引号(+
),"key": "",
会使不捕获任何内容,而.*
会在这种情况下为您提供空字符串。一个细节可能无关紧要,但它们是不同的。
请注意,在正则表达式中使用单个文字空间 很容易被忽略(或加倍),如果稍后添加/x
,也会被吞下,如果引入错误,则会引发错误未经测试。
指定单个简单空间的更好方法?我们可以通过charnames
pragma使用\x20
或Unicode \N{SPACE}
。感谢Borodin提出这个并指定这两个。
来自Sinan Ünür的一个很好的解决方法是使用仅包含空格的字符类/a [ ] b/x
。这两者都强调文字空间是有意的(没有/x
),并允许它在/x
下。
另一个解决方法是明确地转义它,/\ /
,它会引起对它的注意并保护它免受/x
的攻击。</ p>
答案 1 :(得分:2)
你应该用这个:
"key": "(.*?)"
在正则表达式检查中执行:
if($line =~ /"key": "(.*?)",/){
...
这样,第一个捕获组($1
)将包含您想要的内容。
答案 2 :(得分:0)
这是我要写的。它会扫描输入文件中的每一行以获取两个双引号字符串,然后打印第二个字符串(如果它在那里)
use strict;
use warnings 'all';
my ($file) = @ARGV;
open my $fh, $file or die qq{Could not open "$file": $!};
while ( <$fh> ) {
my ($key, $val) = / " ( [^"]+ ) " /xg;
next unless $key and $key eq 'key';
print $val, "\n" if $val;
}