使用纯 sed:
#!/bin/sed -f
x
G
: loop
s:\([^/]*\)/*\(.*\n\)\([^|]*\)|\s:\2\3\1/:
t loop
s/.*\n//
s:/*$::
h
为此,我们必须使用保持空间(辅助缓冲区)来存储先前的 dir 路径。然后我们可以从保留空间中删除目录并将它们替换到相应的 |s 中。更详细的解释如下:
该脚本对每一行执行。我们要做的第一件事是交换(“x”)保持空间和模式空间。最初,保留空间将为空,但在第一行之后,保留空间将包含先前的目录路径。通过交换它们,我们加载先前的目录并将当前的新目录保存到保持空间中。
接下来,我们将新目录名称附加到先前的目录路径(但两者都将用换行符分隔)。用于此的命令是“G”。
现在我们必须为每个 | 循环 我们发现的性格。要做到这一点是棘手的部分,所以请耐心等待。假设我们在当前模式空间中有以下内容
Folder/subdir
| | deeper-subdir
- 首先,
\([^/]*\)
匹配第一个斜线之前的所有内容并捕获它(即,将其存储在一个“变量”中,\1
因为它是第一个捕获组而命名)。
- 然后我们跳过斜杠:
/*
- 将所有内容捕获到换行符(包括)并存储到 capture
\2
:\(.*\n\)
- 捕捉前的一切| 字符并存储到捕获中
\3
:
\([^|]*\)
- 跳过 | 字符后跟一个空格字符:
|\s
现在,捕获看起来像这样:
- 文件夹
- 子目录\n
3.
我们所要做的就是重新生成重新排列捕获的行并添加另一个斜线,这样它们就变成了:
subdir
Folder/| deeper-subdir
之后,我们有一个条件分支命令“t”,如果前一个“s”命令成功,它只会返回到“循环”标签。这意味着当字符串准备好(不再有 |s)时,我们可以退出循环并继续执行代码。
按照示例,下一次迭代包含捕获:
- 子目录
- \n
- 文件夹/
在循环之后,第一个替换命令删除第一行,其中包含新目录尚未进入的路径(即,新目录比前一个目录“浅”)。
最后一个替换命令从行尾删除所有斜杠,最后一个命令是一个保持命令(“h”),它将当前生成的路径复制到保持空间,因此我们可以为下一行重复所有操作。
希望这会有所帮助=)