Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 使用vim将缩进目录列表转换为完整路径_Regex_Vim - Fatal编程技术网

Regex 使用vim将缩进目录列表转换为完整路径

Regex 使用vim将缩进目录列表转换为完整路径,regex,vim,Regex,Vim,我继承了一组带有缩进目录列表的文件,如下所示: DirA/ DirA1/ DirA2/ DirA2.1/ DirA3/ DirB/ DirC/ DirC1/ DirC1.1/ DirC1.1.1/ DirC1.2/ 迪拉/ 迪拉1/ 迪拉2/ DirA2.1/ 迪拉3/ 肮脏的/ 迪尔克/ DirC1/ 目录1.1/ 第1.1.1条/ 第1.2节/ 为了迁移到新代码和新结构,我需要在每一行上将其更改为完整路径 DirA/ DirA/DirA1/

我继承了一组带有缩进目录列表的文件,如下所示:

DirA/ DirA1/ DirA2/ DirA2.1/ DirA3/ DirB/ DirC/ DirC1/ DirC1.1/ DirC1.1.1/ DirC1.2/ 迪拉/ 迪拉1/ 迪拉2/ DirA2.1/ 迪拉3/ 肮脏的/ 迪尔克/ DirC1/ 目录1.1/ 第1.1.1条/ 第1.2节/ 为了迁移到新代码和新结构,我需要在每一行上将其更改为完整路径

DirA/ DirA/DirA1/ DirA/DirA2/ DirA/DirA2/DirA2.1/ DirA/DirA3/ DirB/ DirC/ DirC/DirC1/ DirC/DirC1/DirC1.1/ DirC/DirC1/DirC1.1/DirC1.1.1/ DirC/DirC1/DirC1.2/ 迪拉/ DirA/DirA1/ DirA/DirA2/ DirA/DirA2/DirA2.1/ DirA/DirA3/ 肮脏的/ 迪尔克/ DirC/DirC1/ DirC/DirC1/DirC1.1/ DirC/DirC1/DirC1.1/DirC1.1.1/ DirC/DirC1/DirC1.2/
我更愿意为此使用
vim
(如果只是为了增加我的vim fuu),但我还没有找到如何做到这一点(使用正则表达式、寄存器和/或宏?)。谁能给我一些指点吗?非常感谢。

你能试试这个正则表达式吗:

/^(.+\/)((\r?\n(\s\s){1,}\S+){0,})\r?\n\s\s(\S+)/gm
并替换为以下内容之一:

$1$2\n$1$5
$1$2\r\n$1$5
(如果需要
\n
换行符或
\r\n

演示:

工作原理:

  • 捕获第一个目录(之前没有
    \s
  • 捕获所有行,直到行有
    \s\s
    ,而下一行开头没有
    \s
    。它是最后一个子目录
  • 将父目录添加到最后一个子目录并删除
    \s\s
  • 继续这个循环
  • 对于接下来的步骤,将最后一个
    \s\s
    更改为
    \s{4}
    和下一个
    \s{6}
    ,然后

我不知道
vim
,但希望这个正则表达式模式有帮助

假设缩进宽度为2个空格:

:%s#^\s\+#\=join(split(getline(line('.')-1),'/')[:strlen(submatch(0))/2-1],'/').'/'
概述 其思想是获取前一行(
getline(line('.')-1)
)并将该行拆分为目录。然后根据缩进级别,在前导空格上进行替换,并替换为前一行目录列表的子列表,
strlen(submatch(0))/2-1

细节的荣耀
  • %s#^\s\+{replacement}
    -对以空格开头的行进行替换
  • \={expr}
    将产生
    {expr}
    的结果作为空格的替换-这称为子替换表达式
  • getline(line('.')-1)
    -获取前一行
  • split(getline(line('.')-1),'/')
    -将前面的行拆分为目录段
  • lst[{start}:{end}]
    从列表创建一个子列表,
    lst
    ,从
    {start}
    开始,在索引
    {end}
    结束
  • lst[:{end}]
    -假设列表开始。e、 g
    [0,1,2][:1]
    产生
    [0,1]
  • submatch(0)
    -在子替换表达式中
    submatch({n}
    将获取捕获组编号,
    {n}
  • 子匹配(0)
    将生成替换的整个匹配模式。在正常替换中,也称为
    \0
    &
  • strlen(子匹配(0))/2
    将获取当前行的缩进级别
  • strlen(submatch(0))/2-1
    将减少1个缩进级别。aka。当前行和上面的行共同拥有的目录结构部分
  • join({lst},{glue})
    -以
    {glue}
    作为列表项之间的分隔符,将列表作为字符串连接在一起
  • 当它被
    split()取出时,在末尾添加一个
    /
  • 重要的是要知道Vim从顶部开始逐行替换(如@Lieven Keersmaekers所述)。这意味着我们可以使用前一行来获得共同祖先
有关更多帮助,请参阅:

:h :s
:h sub-replace-expression
:h getline()
:h line()
:h join()
:h sublist
:h strlen()
:h split()

我只是用在线工具测试我的答案,它是有效的。如果你有任何问题,让我们知道!OP正试图通过将父目录包含到每个子目录来将文本从文件1更改为文件2。我认为此文本是输入,需要更改为新文本@Meninx-メネンックス因此,您知道您的解决方案并没有回答OP的问题!感谢您的建议。我使用了Peter的oneliner,因为学习它更有趣,而且它是解决我所面临问题的一步解决方案。但是就像在perl中一样,vim有不止一种方法来做事情。哦,天哪。我们真的需要类似excel的功能来评估一步一步地评估一个公式。我可以算出其中的大部分,但试图将它应用到一行上,这让我很头疼。你可能想补充一点,这是有效的,因为vim一行一行地替换了一行,所以你有(并且需要)替换掉当前行的行-1(我希望我能说清楚)。下面的
[:]
返回列表子集的符号可能也值得一提。我从您的oneliner(再次)中学到了很多,tx.@LievenKeersmaekers我已经将其转换为一个替换并添加了一个descriptionI我实际上喜欢全局命令,因为它教会了我额外的东西,但是vimwise,更短更好。这一个在我的vimtips中!@Theoturi,
getline(line('.)-1)
将产生一个空字符串。你可以通过
:echo getline(0)来测试它
。我通过对模式使用
^\s\+
而不是
^\s*
来避免此问题。这确保了始终存在父目录。