我有一个程序可以提供如下输出:
1405565344
|
+- 1405722995
| |
| +- 1405722998
| | |
| | +- 1405724849
| |
| +- 1406051621
|
+- 1406051709
+- 1406733328
[END OF OUTPUT -- OUTPUT DOES NOT INCLUDE THIS LINE]
请注意,最后一行不是输出的一部分;如果我不在它们之后添加内容,则隐藏最后两行(通常为空白)。另请注意,最后一个条目后面的空白行上有多个空格,但SO不显示它们。
所以我想让它更紧凑,更好..漂亮。使用以下sed
命令...
sed -e 's,|,│,g' \
-e "s,+,└," \
-e "s,- ,─," \
-e '/^[ │]*$/d'
我可以将上面的输入转换为:
1405565344
└─1405722995
│ └─1405722998
│ │ └─1405724849
│ └─1406051621
└─1406051709
└─1406733328
好多了。理想情况下,我希望它是这样的:
1405565344
├─1405722995
│ ├─1405722998
│ │ └─1405724849
│ └─1406051621
├─1406051709
└─1406733328
我知道,差别很小,但它更有意义,更符合我程序的其他输出。
所以基本上:我想要一种让sed
有条件地用+
或└
替换├
的方法,具体取决于它之后的行。看起来几乎是不可能的,没有完全不同的轨道。
有什么想法吗?
答案 0 :(得分:2)
sed -n -e '/| *$/ d;1h;1!H
$ {x
:a
s/\(\n[ |]*\)+\([^[:cntrl:]]*\1[|+]\)/\1├\2/;t a
:b
s/\(\n[ |]*\)+/\1└/;t b
s/|/│/g;s/- /─/g;p
}' YourFile
应该做你的工作。使用其他字符进行测试而非图形化(不要传递给我的aix)。
如果从一行上的行开始直到T
与下一个开头(第一个新行之后的那个)相同的模式,则测试变为+
。我使用[:cntrl:]来捕获非换行符,所以如果有特殊的char被认为是控制字符,它就会失败(不要认为你的文件中有)。
如果不是这种情况(与+一致)改变角落中的de plus [为优化sed模式分组而修改] [为角焦点修改并且具有相同模式的2连续行的情况以+结尾]
答案 1 :(得分:1)
awk方式
可能会得到认真改进,但它可以按预期工作
我的机器无法显示├
或└
,因此请将#
和L
替换为它们。
如果有人有任何改进,请告诉我,我会更新!
awk '/\+/{a=$0;b=index($0,"+");next}
a{if(substr($0,b,1)=="|"){$0=gensub(/+/,"#","g",a)}else{$0=gensub(/+/,"L","g",a)}}
/[1-9]/{print $0}' file
1405565344
#- 1405722995
| #- 1405722998
| | L- 1405724849
| L- 1406051621
L- 1406051709
答案 2 :(得分:1)
这样做。 gawk的match()函数设置变量RSTART。我检查以下行以查看该位置的字符。
gawk '
function g(line) {
gsub(/#/, "├", line)
gsub(/-/, "─", line)
gsub(/[+]/, "└", line)
gsub(/[|]/, "│", line)
return line
}
/^[[:blank:]|]*$/ {next}
prev {
while (match(prev, /[+]/)) {
c=substr($0, RSTART, 1);
if (c == "+" || c == "|")
sub(/[+]/, "#", prev)
else
break
}
print g(prev)
}
{prev=$0}
END {print g($0)}
' file
行动中:
$ echo "1405565344
|
+- 1405722995
| |
| +- 1405722998
| | |
| | +- 1405724849
| |
| +- 1406051621
| +- foobar
|
+- 1406051709
+- barfoo" |
awk '
function g(line) {
gsub(/[+]/, "└", line)
gsub(/#/, "├", line)
gsub(/-/,"─", line)
gsub(/[|]/, "│", line)
return line
}
/^[[:blank:]|]*$/ {next}
prev {
while (match(prev, /[+]/)) {
c=substr($0, RSTART, 1);
if (c == "+" || c == "|")
sub(/[+]/, "#", prev)
else
break
}
print g(prev)
}
{prev=$0}
END {print g($0)}
'
1405565344
├─ 1405722995
│ ├─ 1405722998
│ │ └─ 1405724849
│ ├─ 1406051621
│ └─ foobar
├─ 1406051709
└─ barfoo
答案 3 :(得分:0)
我的逻辑是使用awk,|作为标记化器并使用$ NF的长度来决定要打印的行
cat <ip_file.txt> | awk -F'|' '{if(length($NF)>5)print $0;}'
我输入了以下输出
1405565344
+- 1405722995
| +- 1405722998
| | +- 1405724849
| +- 1406051621
+- 1406051709
注意:替换+ - 仍处于待决状态