如何匹配单个空格分隔的单词与多个空格分隔的单词

时间:2012-10-03 18:45:14

标签: regex perl regex-greedy lookbehind negative-lookbehind

我需要将键和值与下面的文本分开

  

学生证:0
  部门ID = 18432
  名称XYZ

Subjects:
Computer Architecture
Advanced Network Security 2

在上面的示例中,学生ID,部门ID和名称是键,0,18432,XYZ是值。键通过:,=或多个空格与值分隔。我试过像

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

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

我得到的输出是 line是学生ID:0 key是Student,值是ID:0 虽然我想要密钥是学生ID,值是0.对于像主题:和计算机体系结构这样的行,密钥应该有主题和计算机体系结构。我没有值或冒号后有逻辑,我将字符串附加到上一个键,所以看起来像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。

2 个答案:

答案 0 :(得分: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;
   ...
}

答案 1 :(得分:1)

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

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

这应该捕获单字和双字密钥。