我试图从一个输入字符串创建一个Perl哈希,但我对原始的“split”有问题,因为值可能包含引号。下面是一个输入字符串示例,以及我的(期望的)结果哈希:
my $command = 'CREATE:USER:TEL,12345678:MOB,444001122:Type,Whatever:ATTRIBUTES,"ID,0,MOB,123,KEY,VALUE":TIME,"08:01:59":FIN,0';
my %hash =
(
CREATE => '',
USER => '',
TEL => '12345678',
MOB => '444001122',
Type => 'Whatever',
ATTRIBUTES => 'ID,0,MOB,123,KEY,VALUE',
TIME => '08:01:59',
FIN => '0',
);
输入字符串的长度是任意的,并且没有设置键的数量。
谢谢!
-总部
这似乎是Text::ParseWords
可以处理的。quotewords
子例程将分割分隔符:
上的输入,忽略引号内的分隔符。这将为我们提供项目的基本列表,首先在输出中显示为$VAR1
。之后,只需使用正则表达式解析逗号分隔的项,正则表达式将处理可选的第二次捕获,以容纳空标记,例如CREATE
和USER
的标记。
use strict;
use warnings;
use Data::Dumper;
use Text::ParseWords;
while (<DATA>) {
chomp;
my @list = quotewords(':', 0, $_);
my %hash = map { my ($k, $v) = /([^,]+),?(.*)/; $k => $v; } @list;
print Dumper \@list, \%hash;
}
__DATA__
CREATE:USER:TEL,12345678:MOB,444001122:Type,Whatever:ATTRIBUTES,"ID,0,KEY,VALUE":TIME,"08:01:59":FIN,0
输出:
$VAR1 = [
'CREATE',
'USER',
'TEL,12345678',
'MOB,444001122',
'Type,Whatever',
'ATTRIBUTES,ID,0,KEY,VALUE',
'TIME,08:01:59',
'FIN,0'
];
$VAR2 = {
'TIME' => '08:01:59',
'MOB' => '444001122',
'Type' => 'Whatever',
'CREATE' => '',
'TEL' => '12345678',
'ATTRIBUTES' => 'ID,0,KEY,VALUE',
'USER' => '',
'FIN' => '0'
};
据我所知,最明显的候选者——Text::CSV
——无法正确处理这种格式,因此只有一种自制的正则表达式解决方案。
use strict;
use warnings;
my $command = 'CREATE:USER:TEL,12345678:MOB,444001122:Type,Whatever:ATTRIBUTES,"ID,0,KEY,VALUE":TIME,"08:01:59":FIN,0';
my %config;
for my $field ($command =~ /(?:"[^"]*"|[^:])+/g) {
my ($key, $val) = split /,/, $field, 2;
($config{$key} = $val // '') =~ s/"([^"]*)"/$1/;
}
use Data::Dumper;
print Data::Dumper->Dump([\%config], ['*config']);
输出
%config = (
'TIME' => '08:01:59',
'MOB' => '444001122',
'Type' => 'Whatever',
'CREATE' => '',
'TEL' => '12345678',
'ATTRIBUTES' => 'ID,0,KEY,VALUE',
'USER' => '',
'FIN' => '0'
);
如果你有Perl v5。10或更高版本之后,您就有了方便的(?|…)
正则表达式组,它允许您编写
use 5.010;
use warnings;
my $command = 'CREATE:USER:TEL,12345678:MOB,444001122:Type,Whatever:ATTRIBUTES,"ID,0,KEY,VALUE":TIME,"08:01:59":FIN,0';
my %config = $command =~ /(\w+) (?| , " ([^"]*) " | , ([^:"]*) | () )/gx;
use Data::Dumper;
print Data::Dumper->Dump([\%config], ['*config']);
这将产生与上面代码相同的结果。
使用Text::CSV。它可以正确处理逗号分隔的值文件
标准模块似乎无法解析您输入的格式,即使使用sep_char
和allow_loose_quotes
。因此,您必须自己完成繁重的工作,但仍然可以使用Text::CSV解析每个键值对:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);
use Data::Dumper;
use Text::CSV;
my $command = 'CREATE:USER:TEL,12345678:MOB,444001122:Type,Whatever:ATTRIBUTES,"ID,0,KEY,VALUE":TIME,"08:01:59":FIN,0';
my @fields = split /:/, $command;
my %hash;
my $csv = Text::CSV->new();
my $i = 0;
while ($i <= $#fields) {
if (1 == $fields[$i] =~ y/"//) {
my $j = $i;
$fields[$i] .= ':' . $fields[$j] until 1 == $fields[++$j] =~ y/"//;
$fields[$i] .= ':' . $fields[$j];
splice @fields, $i + 1, $j - $i, ();
}
$csv->parse($fields[$i]);
my ($key, $value) = $csv->fields;
$hash{$key} = "$value"; # quotes turn undef to q()
$i++;
}
print Dumper \%hash;
我收到了很多文件,其中我的控制为零,我需要根据分隔符进行拆分。但是当分隔符在引号内时,我不想拆分。因此,列 1、列 2、列 3 是 然而,column1、“column2”、column3是 这可以使用此正则表达式(在 C# 下) 现在,我的问题是当有一行只有一个双引号(仅打开或关闭)时,例如第1列,第2列",第3列返回 虽然它应该返回 我发现很多与正则表达式相关的,但在上面的特定示例中,它们都失
问题内容: 仅使用正则表达式方法,方法String.replaceAll和ArrayList如何将字符串拆分为标记,但忽略引号内存在的定界符?分隔符是非字母数字或带引号的文本的任何字符 例如:字符串: 你好^世界’这*有两个令牌’ 应该输出: 你好 worldthis *有两个令牌 问题答案: 使用a 来标识要保留的部分,而不是要拆分的部分: 看到它在线上工作:ideone
问题内容: 我的文字如下: 谁能告诉我我必须使用哪些正则表达式分度数才能获得以下结果: 我在这里阅读Sun教程,直到“ Matcher类的方法”为止,但我仍然茫然。谢谢! 如果是这样,那将很容易,但是不幸的是,事实并非如此。有任何想法吗? 问题答案: 您可以直接使用split()方法,如下所示: (请注意,这将返回长度为5的数组,第一个位置为空字符串) 或者,如果您想使用模式/匹配器,可以这样做:
问题内容: 我正在寻找将其转换为6个元素的数组:a,b,c,“ d,e,f”,g,h。我正在尝试通过Javascript执行此操作。这是我到目前为止所拥有的: 但是现在,它会将双引号中的所有内容都分割开了,这是不正确的。 编辑:好的,抱歉,我对这个问题的措辞很差。给我一个字符串而不是数组。 我想使用“ split”功能将 其 转换为数组。 问题答案: 这就是我要做的。
问题内容: 我已经看到了许多相关的问题,但是都没有直接解决我想做的事情。我正在从CSV文件中读取文本行。 所有项目都用引号引起来,有些则在引号内有其他逗号。我想按逗号分隔行,但忽略引号内的逗号。有没有一种方法可以在Python中执行此操作,而无需使用许多正则表达式语句。 一个例子是: 我想将其解析为4个单独的值变量: 我想念一个简单的选择吗? 问题答案: 不要尝试重新发明轮子。 如果要读取CSV文
输入字符串用逗号分隔。但它可能包含双引号内的逗号,需要忽略。下面是示例字符串 下面是我用来拆分逗号的代码,但如果逗号是双引号中字符串的一部分,它就会失败。 所以任何解决这个问题的想法。