为什么这个正则表达式(尝试匹配“@”字符之间的字符)会失败?

为什么这个正则表达式(尝试匹配“@”字符之间的字符)会失败?

我需要提取 GEDCOM 文件中选定行的第二个字段。这些行均采用以下格式:

% grep @ /tmp/XYZ | tail -5
0 @X701@ OBJE
0 @X702@ OBJE
0 @X750@ OBJE
0 @X765@ OBJE
0 @X766@ OBJE

但接下来,

% egrep "0 \@[^@]\@" /tmp/XYZ
% perl -CSD -p -i -e 's:0 @([^@])@ .*:ZYX \1:g;' /tmp/XYZ

第一个没有发现任何东西,第二个也没有改变任何东西;我不明白为什么。

CSD是因为虽然该文件大部分是 ASCII,但它包含一些法语、波兰语和中文,并且采用 UTF-8 编码。

据我所知,@对于正则表达式来说,不是一个特殊字符。

更新:我正在寻找具有主键功能的字段。它始终由 分隔@,因此不能包含@。有些行可能会引用这样的键,但只有当行以 开头时,它才是主键0。我必须不是匹配包含其他内容的行@,但应通过添加 string-begin 来确保匹配^。我还必须不是命中其他格式的行 - 我使用 grep 来显示目标行的格式,并使用 tail 将大小限制为少于五千。

答案1

  1. 如果你可能有如下代码
    60 @FOO@ blah
    
    或者
    42.0 @记鬼四七@ quux
    
    (并且您不想匹配它们),您应该以 ; 开头您的正则表达式 ^,例如,  ^0 @…
  2. [^@]将匹配X或 。要匹配两个字符之间7的任意数量的非@字符(例如 ) ,您需要或 ; 例如, X701@[^@]*[^@]+
    % egrep '^0 @[^@]*@' /tmp/XYZ
    % perl -CSD -p -i -e 's:^0 @([^@]*)@ .*:ZYX \1:g;' /tmp/XYZ
    
    如果两个字符之间+必须至少有一个非字符,则 使用。除非 plain失败,否则不要使用。@@\@@
  3. 为了避免匹配具有第三行的行@,请使用另一个[^@]* 来指定该行的其余部分是除之外的字符 @
    % egrep '^0 @[^@]*@ [^@]*$' /tmp/XYZ
    

相关内容