我不在乎我是否通过vim,sed,awk,python等实现了这一点。我尝试过,无法完成它。
对于这样的输入:
top f1 f2 f3
sub1 f1 f2 f3
sub2 f1 f2 f3
sub21 f1 f2 f3
sub3 f1 f2 f3
我想:
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
然后我想在Excel中加载它(由空格分隔)并且仍然可以查看第一列的层次结构!
我尝试了很多东西,但最终失去了层次结构信息
答案 0 :(得分:5)
在vim中有两种不同的方法可以做到这一点。
使用正则表达式:
:%s/^\s\+/\=repeat('.', len(submatch(0)))
这是相当简单的,但有点冗长。它使用eval寄存器(\=
)生成一个'.'
字符串,其长度与每行开头的空格数相同。
使用norm命令:
:%norm ^hviwr.
这是一个更方便的短命令,虽然它有点难以理解。它直观地选择一行开头的空格,并用点替换整个选择。如果没有前导空格,则命令将在^h
上失败,因为光标会尝试移出界限。
要查看其工作原理,请尝试在包含前导空格的行上键入^hviwr.
,以便查看它。
答案 1 :(得分:4)
以此为输入:
$ cat file
top f1 f2 f3
sub1 f1 f2 f3
sub2 f1 f2 f3
sub21 f1 f2 f3
sub3 f1 f2 f3
尝试:
$ sed -E ':a; s/^( *) ([^ ])/\1.\2/; ta' file
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
:a
这会创建一个标签a
。
s/^( *) ([^ ])/\1.\2/
如果该行以空格开头,则用一个句点替换前导空格中的最后一个空格。
更详细地说,^( *)
匹配除了最后一个之外的所有前导空格并将它们存储在组1中。正则表达式([^ ])
(尽管stackoverflow看起来像是什么,但它包含一个空格,后跟([^ ])
)匹配一个空格,后跟一个非空白,并将非空白存储在第2组中。
\1.\2
将匹配的文本替换为第1组,后跟一个句点,然后是第2组。
ta
如果替换命令导致替换,则转回标签a
并重新尝试。
以上是在现代GNU sed上测试的。对于BSD / OSX sed,可能需要也可能不需要使用:
sed -E -e :a -e 's/^( *) ([^ ])/\1.\2/' -e ta file
在古代GNU sed上,需要使用-r
代替-E
:
sed -r ':a; s/^( *) ([^ ])/\1.\2/; ta' file
以上假设空格是空白的。如果它们是标签,那么你必须决定你的tabstop是什么,并相应地进行替换。
答案 2 :(得分:3)
因为您说 python
:
#!/usr/bin/env python
import re, sys
for line in sys.stdin:
sys.stdout.write(re.sub('^ +', lambda m: len(m.group(0)) * '.', line))
(对于每一行,我们用等长的点串'^ +'
)替换最长的前缀空格len(m.group(0)) * '.'
。
最终结果:
$ ./dottify.py <file
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
因为您说 awk
:
$ awk '{ match($0,/^ +/); p=substr($0,0,RLENGTH); gsub(" ",".",p); print p""substr($0,RLENGTH+1) }' file
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
(对于每一行我们匹配match
空格的最长前缀,用substr
提取,用点gsub
替换每个空格,然后打印修改后的前缀{{ 1}},后跟输入行的其余部分(p
和RSTART
变量填充在RLENGTH
之后,并保持匹配模式的起始位置和长度。)
答案 3 :(得分:3)
在awk中。它一直用一个句点替换第一个空格,而空格只在句点之前:
$ awk '{while(/^\.* / && sub(/ /,"."));}1' file
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
这是perl中的一个:
$ perl -p -e 'while(s/(^\.*) /\1./){;}' file
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
答案 4 :(得分:1)
虽然有点冗长,但却是一种有趣的运动:
with open('file.txt', 'r') as f:
data = []
for i, line in enumerate(f):
# Don't do anything to the field names
if i == 0:
new_line = line.rstrip()
else:
n_leading_spaces = count_leading_spaces(line)
# Impute periods for spaces
new_line = ('.'*n_leading_spaces + line.lstrip()).rstrip()
data.append(new_line)
最后,打开文件并做一些工作:
>>> print('\n'.join(data))
top f1 f2 f3
...sub1 f1 f2 f3
...sub2 f1 f2 f3
......sub21 f1 f2 f3
...sub3 f1 f2 f3
结果:
with open('file.txt', 'r') as f:
data = []
for i, line in enumerate(f):
# Don't do anything to the field names
if i == 0:
new_line = line.rstrip()
else:
n_leading_spaces = len(line) - len(line.lstrip())
# Impute periods for spaces
new_line = line.lstrip().rjust(len(line), '.').rstrip()
data.append(new_line)
你也可以这样做,这更简单:
.form-horizontal