3

我需要将键和值与如下所示的文本分开

学生 ID:0
部门 ID = 18432
姓名 XYZ

Subjects:
Computer Architecture
Advanced Network Security 2

在上面的示例中,Student ID、Department ID 和 Name 是键,0,18432、XYZ 是值。键与值通过 :,= 或多个空格分隔。我尝试了reg ex,例如

    $line =~ /(([\w\(\)]*\s)*)([=:\s?]?)\s*(\S.*)?$/;
    $key   = $2;
    $colon=$3;
    $value = $4;

我面临的问题是确定一个单词何时用单个空格分隔以及何时被多个空格分隔。

我得到的输出是 line is Student ID: 0 key is Student , value is ID: 0 而我想要 key is Student ID 并且 value 是 0. 对于像 Subjects: 和 Computer Architecture 这样的行,键应该有 Subjects 和 Computer Architecture。稍后当没有值或冒号时我有逻辑,我将字符串附加到前一个键,所以它看起来像 Subjects=Computer Architecture;Advanced Network Security 2

更新:感谢 Ikegami 指出我使用后视运算符。但我似乎仍然无法解决它。

$line=~/^(?: ( [^:=]+ ) (?<!\s\s)\s* [:=]\s*|\s*)(.*)$/x;

所以当我说(?<!\s\s)\s* [:=]\s*|\s*我的意思是当有两个以上的空间时,消耗所有的空间,当没有两个连续的空间时,寻找 : 或 = 并消耗空间。因此,如果您将下面的行传递给表达式,我不应该得到 $1=Name 和 $2=ABC XYZ 吗?

Name         ABC XYZ

我似乎得到的是键是空的,值是名称 ABC XYZ。

4

2 回答 2

4

如果

Name Eric Brine
Computer Architecture x86

方法

key: Name Eric               value: Brine
key: Computer Architecture   value: x86

那么你想要

# Requires 5.10
if (/
   ^
   (?: (?<key> [^:=]+ (?<!\s) ) \s* [:=] \s* (?<val> .*  )
   |   (?<key> .+     (?<!\s) ) \s+          (?<val> \S+ )
   )
   \s* $
/x) {
   my $key = $+{key};
   my $val = $+{val};
   ...
}

或者

if (/
   ^
   (?: ( [^:=]+ (?<!\s) ) \s* [:=] \s* ( .*  )
   |   ( .+     (?<!\s) ) \s+          ( \S+ )
   )
   \s*
   ( .* )
/x) {
   my ($key,$val) = defined($1) ? ($1,$2) : ($3,$4);
   ...
}

如果

Name Eric Brine
Computer Architecture x86

方法

key: Name       value: Eric Brine
key: Computer   value: Architecture x86

那么你想要

# Requires 5.10
if (/
   ^
   (?: (?<key> [^:=]+ (?<!\s) ) \s* [:=]
   |   (?<key> \S+ ) \s
   )
   \s*
   (?<val> .* )
/x) {
   my $key = $+{key};
   my $val = $+{val};
   ...
}

或者

if (/
   ^
   (?: ( [^:=]+ (?<!\s) ) \s* [:=]
   |   ( \S+ ) \s
   )
   \s*
   ( .* )
/x) {
   my $key = defined($1) ? $1 : $2;
   my $val = $3;
   ...
}

请注意,您可以删除所有空格和换行符。例如,最后一个片段可以写成:

if (/^(?:([^:=]+(?<!\s))\s*[:=]|(\S+)\s)\s*(.*)/) {
   my $key = defined($1) ? $1 : $2;
   my $val = $3;
   ...
}
于 2012-10-03T18:53:55.750 回答
1

尝试将关键部分指定为两个文本位,中间有一个可选空格;

$line =~ /([\w\(\)]*\s?[\w\(\)]*)\s*([=:]?)\s*(\S.*)?$/;

这应该捕获一个单词和两个单词的键。

于 2012-10-03T18:50:31.877 回答