Regex:在特定单词后替换空格

5cnsuln7  于 2023-11-20  发布在  其他
关注(0)|答案(4)|浏览(139)

我试图(但失败了)写一个正则表达式(PCRE 2),它将在特定单词(即·货车·,·VON·或·DE·)的第一个示例之后用破折号(-)替换每个空格,这些单词本身必须被空格包围。
举例来说:

HENRIETTA VON DER GRAAF
CAROLINE VAN OOSTEN DE WINKEL
MARC DE VRIES VAN JONG
ANNEKA VANHOVEN BAKKER
JOHN WILKINSON SMITH

字符串
将翻译为:

HENRIETTA VON-DER-GRAAF
CAROLINE VAN-OOSTEN-DE-WINKEL
MARC DE-VRIES-VAN-JONG
ANNEKA VANHOVEN BAKKER (NB: Does not match VAN as not surrounded by spaces)
JOHN WILKINSON SMITH (NB: No substitution here as pattern not matched)


这是我所得到的,但它并没有替换匹配之后的所有空格:

\b( VON| VAN| DE)+\s


https://regex101.com/r/s6BC1y/1
任何建议最赞赏!

rjzwgtxy

rjzwgtxy1#

这可以通过\G\K来实现:

(?:                # Match either
  (?<!\S)          #                      but only if it is not preceded by a whitespace,
  (?:VON|VAN|DE)   # 'VON', 'VAN' or 'DE'
|                  # or
  \G(?!\A)         # the end of the last match
  \S+              # then a sequence of non-whitespace characters.
)                  # 
\K\x20             # Forfeit everything we just match, then match a space.

字符串
试试on regex101.com
由于PCRE 2中缺乏对非固定宽度lookbehind的支持,我们无法执行以下操作,这可能更容易理解:

(?<=               # Match a position preceded by
  (?:VON|VAN|DE)   # either of the three words
  (?:\x20\S+)*     # then 0 or more (space + word),
)                  # 
\x20               # and a space at that position.


试试on regex101.com
\G匹配最后一个匹配项的末尾 * 或整个字符串的开头 *。由于(?!\A),只有当我们匹配第一个匹配项(?<!\S)(?:VON|VAN|DE)时,后一个匹配项才会匹配。
一个直观的解释:

MARC DE VRIES VAN JONG
     ^ Start matching `(?<!\S)(?:VON|VAN|DE)`
MARC DE VRIES VAN JONG
       ^ ...then `\x20`.
MARC DE VRIES VAN JONG
        ^ `(?<!\S)(?:VON|VAN|DE)` doesn't match here; switch to `\S+`
MARC DE VRIES VAN JONG
             ^ `\x20` is matched.
MARC DE VRIES VAN JONG
              ^ Back to step 1.
MARC DE VRIES VAN JONG
                  ^ Back to step 3.
a2mppw5e

a2mppw5e2#

您可以在没有正则表达式的情况下进行转换。

data have;
input text $CHAR50.;
datalines;
HENRIETTA VON DER GRAAF
CAROLINE VAN OOSTEN DE WINKEL
MARC DE VRIES VAN JONG
ANNEKA VANHOVEN BAKKER
JOHN WILKINSON SMITH
;

data want;
  set have;
  p = prxmatch('m/\b(VAN|VON|DE)( )/',text);
  if 0 < p < length(text) then 
    substr(text,p+1) = translate(substr(trim(text),p+1),'-',' ');
run;

字符串


的数据

rseugnpd

rseugnpd3#

你可以使用这个正则表达式来实现你想要的结果:

^(.*? (?:VAN|VON|DE)) |((?<!^)\G\w+)

字符串
这匹配:

  • ^(.*? (?:VAN|VON|DE)):行首后的最小字符数,后跟一个空格,以及VONVANDE中的一个,所有字符都在第1组中捕获,然后是一个空格;或
  • ((?<!^)\G\w+):从最后一个成功匹配的末尾开始(但不是在字符串的开头,\G通常允许这样),在第2组中捕获的一些单词字符,然后是一个空格

然后,您可以使用$1$2-替换匹配项($1$2中只有一个会有内容)。
regex101上的正则表达式演示
请注意,正则表达式可以使用\K来简化,以丢弃匹配的第一部分,只匹配单词后面的空格:

^.*? (?:VAN|VON|DE)\K |(?<!^)\G\w+\K


然后,替换为-
regex101上的正则表达式演示

xhv8bpkk

xhv8bpkk4#

使用Perl:

perl -anE '
    if (/\b(?:VON|VAN|DE)\b/) {
        @a = split /\s+/;
        say $a[0], " ", join "_", @a[1..$#a]
    } else {
        print;
    }
' file

字符串

HENRIETTA VON_DER_GRAAF
CAROLINE VAN_OOSTEN_DE_WINKEL
MARC DE_VRIES_VAN_JONG
ANNEKA VANHOVEN BAKKER
JOHN SMITH

相关问题