2

我有一个制表符分隔的文件(包含 2 列),格式如下:

ABA-1 (tab)           CDF@
ABA-1 (tab)           EFG
ZYA (tab)             ABA-1 this
EFG that this (tab)   ZYA

我只想匹配 /EFG/ 而不是 /EFG 匹配 this/. 同样,我只想匹配 /ABA-1/ 而不是 /ABA-1 this/。

以下模式不起作用:

$line=~ /^(\w*\-?\w*\@?)\t*(\w*\-?\w*\@?)$/

我曾尝试使用单词边界 (\b),但它也不起作用。

关于如何解决这个问题的任何想法?任何帮助将不胜感激。非常感谢!

4

3 回答 3

3

您的正则表达式不起作用有几个原因。首先,您的选项卡不能是可选的,否则该行将无法正确拆分。其次,您的模式中没有任何内容可以解释您想要匹配的部分之后that this的可能字符,即没有任何内容 match 。

您可以通过在每次捕获后添加来解决第一个问题.*?(或者,对于第二次捕获,只需删除尾随$锚点)。\t*只需更改为 即可解决第二个问题\t

此修改适用于您的示例数据

$line =~ /^(\w*\-?\w*\@?).*?\t(\w*\-?\w*\@?).*?$/

但它不是很漂亮!

看起来您只想在制表符或行首之后直接包含所有非空格字符

该程序将该想法编码为正则表达式

use strict;
use warnings;

my @data = (
  "ABA-1\tCDF@",
  "ABA-1\tEFG", 
  "ZYA\tABA-1 this",
  "EFG that this\tZYA",
);

for (@data) {
  my @fields = /(?:^|\t)(\S+)/g;
  print "@fields\n";
}

输出

ABA-1 CDF@
ABA-1 EFG
ZYA ABA-1
EFG ZYA
于 2012-10-16T10:41:32.490 回答
1
$line=~ /^(\w+)[^\t]*\t(\w+).*$/

这将仅捕获 . 之前和之后的第一个单词tab

更新: - 如果你想any non-space在第一个空格之前匹配字符,那么你可以试试这个模式: -

my $line = "ABA-1\tCDF@";
my $line1 = "ZYA \t  ABA-1 this";

if ($line=~ /^([^\s]+)[^\t]*\t\s*([^\s]+).*$/) {    
    print "$1 $2";
}

if ($line=~ /^([^\s]+)[^\t]*\t\s*([^\s]+).*$/) {    
    print "$1 $2";
}

输出: -

ABA-1 CDF@
ZYA ABA-1
于 2012-10-16T10:21:12.447 回答
1

这将匹配由一行中的单个制表符分隔的两个单词(不包含空格):

$line=~ /^(\w+)\t(\w+)$/

更新:这将排除任何具有“ABA this”之类的行。但是,也许您只想从“ABA this”中捕获 ABA。这将为您做到这一点:

$line=~ /^([A-Z]+)[^\t]*\t([A-Z]+)/

更新:这是新要求的新模式。它匹配每列中的第一个非空白部分。

$line=~ /^([^\s]+).*\t\s*([^\s]+)/
于 2012-10-16T10:16:18.390 回答