Regex 是否可以通过Vim中的正则表达式替换有条件地插入文本?

Regex 是否可以通过Vim中的正则表达式替换有条件地插入文本?,regex,vim,Regex,Vim,我将从Excel转换为Wiki格式的表格中有几行,如果该字段中有文本,我希望为每行的部分文本添加链接标记。我已开始转换工作,并已达到这一点: |10.20.30.9||x|-|| |10.20.30.10||x|s04|Server 4| |10.20.30.11||x|s05|Server 5| |10.20.30.12||||| |10.20.30.13||||| 我想要的是将第四列从,例如,s04更改为[[server:s04]]。如果行为空,或者包含-,我不希望添加链接括号。如果-是个

我将从Excel转换为Wiki格式的表格中有几行,如果该字段中有文本,我希望为每行的部分文本添加链接标记。我已开始转换工作,并已达到这一点:

|10.20.30.9||x|-||
|10.20.30.10||x|s04|Server 4|
|10.20.30.11||x|s05|Server 5|
|10.20.30.12|||||
|10.20.30.13|||||
我想要的是将第四列从,例如,
s04
更改为
[[server:s04]]
。如果行为空,或者包含
-
,我不希望添加链接括号。如果
-
是个大问题,我可以删除它


我在regex上的所有尝试都是从被替换的整行结束的行中获取任何内容。

考虑使用
awk
执行此操作:

#!/bin/bash

awk -F'|' '
{ 
  OFS = "|";
  if ($5 != "" && $5 != "-")
    $5 = "server:" $5;
  print $0
}'
注意:我从第一个版本开始编辑这个脚本。这是目前的一个,IMO更好

然后,您可以使用以下方法进行处理:

cat $FILENAME | sh $AWK_SCRIPTNAME
-F'|'
开关告诉
awk
使用
|
作为字段分隔符。
if/else
printf
语句都是非常自解释的。仅当字段不是
“-”
时,才会打印字段,并在第5列前面加上“server:”

为什么是第5列而不是第4列?:因为您在每条记录的开头使用了
|
。因此
awk
将“first”字段(
$1
)视为一个空字符串,它认为应该在第一个
|
之前出现

 :1,$s/|\(s[0-9]\+\)|/|[[server:\1]]|/

假设您的s04、s05始终是s和一个数字

可能最好在ArjunShankar编写时使用awk,但如果您删除“-”;,这应该可以工作)没有让它在那里工作

:%s/^\([^|]*|\)\([^|]*|\)\([^|]*|\)\([^|]*|\)\([^|]\+|\)/\1\2\3\4[[server:\5]]/

不过这很愚蠢。前4个是相同的(最多匹配4次)。没有让它与{4}一起工作。第五个匹配s04/s05字符串(只要求它不是空的,因此“-”必须被删除)。

这似乎完成了您在这里放弃的示例的工作(使用Vim):


通过以下方法可以实现更简单的替换:

%s/^|.\{-}|.\{-}|.\{-}|\zs\(\w\{1,}\)\ze|/[[server:\1]]/

   ^^^^^^^^^^^^^^^^^^^^                   -> Match the first 3 groups (empty or not);
                       ^^^                -> Marks the "start of match";
                          ^^^^^^^^^^^     -> Match only if the 4th line contains letters numbers and `_` ([0-9A-Za-z_]);
                                     ^^^  -> Marks the "end of match";

如果
字符类似于
-
,可以出现但不能替换,请使用以下正则表达式:
%s/^.{-}.{-}.{-}.{-}.{-}\zs\([0-9a-zA-Z]\{1,}\)\ze/[[server:\1]/

为其他人给出的想法增加了一点可读性:

:%s/\v^%(\|.{-}){3}\|\zs(\w+)/[[server:\1]]/
工作完成了


请注意{3}如何指示要跳过的列数。还要注意,对于非常神奇的正则表达式模式,使用了
\v
。这降低了正则表达式的复杂性,特别是当它使用比文本更多的“特殊”字符时。

我建议使用以下替换命令

:%s/^|\%([^|]*|\)\{3}\zs[^|-]\+\ze|/[[server:&]]/


你可能不需要正则表达式。你可以简单地用[[服务器[S04] ]搜索和替换“S04”,对吗?但是我希望在同一列中有文本的所有行中加上S04的文本,并且之前的Cube可能包含文本,所以视觉块不起作用。你应该考虑使用<代码> AWK < /C> >,设置'''作为字段分隔符。MyaWiKi标记,因此,重放应该是
|[[server:\1]].
注意,这将替换以下“| 10.20.30.11 | s04 | x | s05 | server 5 |”中的第一个s04”。@JohanSoderberg:是的,但我假设输入与给定的示例类似,因此在第一列中不包含s03。但是你当然是对的。更简单的方法是使用
\{3}
匹配前三个。您还可以使用
[^-|][^-|]*
跳过just
-
的情况。另外,尝试使用
\zs
以避免完全消耗第一节::
:%s/^\%(|[^^]*\){3}\)\zs\([^-\][^^]]*\)/[[server:\1]/
要避免使用大量组,请尝试使用
\zs
\ze
。为了只匹配单词(解决
-
问题),您可以使用以下正则表达式:
\w\{1,}
@MagnunLeno
\w\+/code>与
\w{1,}
有什么不同?@sehe,它们是一样的,我只是习惯使用
{1,}
。但是,
\+
(或
{1,}
)和
{-1,}
)之间存在巨大的差异。第一个是第二个的贪婪版本(匹配尽可能多),匹配尽可能少。这个正则表达式将| after字段4放在[[]]标记内。很好!我完全忘记了我们可以用{3}来减少重复。投票支持这个!这并没有完全奏效。在某些行中,第四个字段为空,但第五个字段中有文本,第五个字段作为链接。这就像一个符咒!。我打算在现场移除-使替换更容易。非常好!这可能是解决这个问题最简单、最好的方法!我注意到一个问题。第4列中包含一个或多个“-”的任何条目都将获得一个链接,该链接围绕零件直至第一个“-”。由于我描述了删除所有只有“-”的条目,正则表达式可以更改为:%s/^ | \%([^ |]*.\)\{3}\zs[^ |]\+/[[server:&]/@user1410444:我可能把规范的这部分搞错了。为了澄清问题:该命令是否应该忽略第四列为连字符或包含连字符的行?
:%s/^|\%([^|]*|\)\{3}\zs[^|-]\+\ze|/[[server:&]]/