TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Show HN: I wrote a program to convert lines of text into trees

333 pointsby birchbabout 4 years ago

21 comments

petethepigabout 4 years ago
Maybe this is not super relevant, but my favorite hack is that any tree-like structure like this can be browsed with ncdu. Here&#x27;s a gist for breaking down redis traffic by command for example: <a href="https:&#x2F;&#x2F;gist.github.com&#x2F;petethepig&#x2F;0f33c910fb2edad8969a5775e23bb99f" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;petethepig&#x2F;0f33c910fb2edad8969a5775e...</a>
评论 #26625604 未加载
评论 #26626440 未加载
birchbabout 4 years ago
Author here: Often I have to digest log files and lists of Azure resource names. I prefer to work with hierarchies of things, so I wrote this simple filter. Turns out to quite handy, especially when combined with awk and its friends.
评论 #26623775 未加载
评论 #26623737 未加载
评论 #26707457 未加载
评论 #26630604 未加载
mklein994about 4 years ago
Neat. I&#x27;ll add this to my toolbox.<p>Somewhat unrelated: I discovered some time ago that the column command (from util-linux) can print trees of hierarchical data (up to 2 levels deep).<p>From the man page:<p><pre><code> $ echo -e &#x27;1 0 A\n2 1 AA\n3 1 AB\n4 2 AAA\n5 2 AAB&#x27; | column --tree-id 1 --tree-parent 2 --tree 3 1 0 A 2 1 |-AA 4 2 | |-AAA 5 2 | `-AAB 3 1 `-AB </code></pre> column(1): <a href="https:&#x2F;&#x2F;github.com&#x2F;karelzak&#x2F;util-linux&#x2F;blob&#x2F;master&#x2F;text-utils&#x2F;column.1.adoc#examples" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;karelzak&#x2F;util-linux&#x2F;blob&#x2F;master&#x2F;text-util...</a>
评论 #26633524 未加载
breckabout 4 years ago
Awesome. You really nailed it. In my experience the output for spreadsheets turns out to be key so good job highlighting that (<a href="https:&#x2F;&#x2F;github.com&#x2F;birchb1024&#x2F;frangipanni#output-for-spreadsheets" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;birchb1024&#x2F;frangipanni#output-for-spreads...</a>).<p>One suggestion: it may help to generalize the newline as the node separator. You may already be doing this (my go is rusty) but instead of <a href="https:&#x2F;&#x2F;github.com&#x2F;birchb1024&#x2F;frangipanni&#x2F;blob&#x2F;7543b4ee15ae7f0491e1212a43b7fc61acc7e00a&#x2F;frangipanni.go#L158" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;birchb1024&#x2F;frangipanni&#x2F;blob&#x2F;7543b4ee15ae7...</a> be able to override the &quot;newline&quot; as the node separator, like you&#x27;ve done with the &quot;spacer&quot; param.<p>What do you do when the same line is encountered?
评论 #26633552 未加载
评论 #26627949 未加载
AnonHPabout 4 years ago
This is really very nice and useful! I read through the examples and thought about something that would be a good addition and then see that “-skip” was just implemented! I can skip (pun intended) using an additional layer of cut or awk because of this.<p>The detailed examples are great too, showing different use cases and features.<p>Thank you very much for creating this tool and sharing it.
softwaredougabout 4 years ago
TIL from the README, you can insert `img` tags into a markdown file, and github will honor the align tag, etc<p>```<p>&lt;img src=&quot;frangipanni.jpg&quot; alt=&quot;A Tree&quot; width=&quot;200&quot; align=&quot;right&quot;&gt;<p>```
eevilspockabout 4 years ago
I love what it does for log files. Abbreviated example from the README:<p><pre><code> May 10 03:17:06 localhost systemd: Removed slice User Slice of root. May 10 03:17:06 localhost systemd: Stopping User Slice of root. </code></pre> becomes:<p><pre><code> May 10 03:17:06 localhost systemd : Removed slice User Slice of root : Stopping User Slice of root</code></pre>
评论 #26632889 未加载
timonokoabout 4 years ago
Seen this about 50 years ago. It was method of saving expensive Teletype ink ribbons. Instead of printing same repeating messages on mainframe log, it printed only those parts that were different from previous line.<p>And of course empty line was &quot;ditto&quot;. Except this wasted paper and was later replaced with &quot;...&quot;.
oandrewabout 4 years ago
There is also<p><pre><code> tree --fromfile </code></pre> e.g.<p><pre><code> echo a&#x2F;b1 a&#x2F;b2&#x2F;c | xargs -n1 | tree --fromfile . └── a ├── b1 └── b2 └── c 2 directories, 2 files</code></pre>
mdeck_about 4 years ago
In retrospect, it’s not clear to me why I somehow expected this project to be something more literally arboreal. I even got my hopes up further when I clicked the link and saw that photo of plumerias.<p>Yet, this project is cool enough that I’m not even disappointed.
评论 #26633620 未加载
motohagiographyabout 4 years ago
This looks like what I always wanted for normalizing data sets and grepping logs but couldn&#x27;t articulate. Thank you!
kevinmgrangerabout 4 years ago
I&#x27;ve been thinking about making something like this for a while, this is great!<p>I always thought it was weird that &quot;do one thing and one thing well&quot; stopped short of dealing with tree representations on the commandline.
评论 #26625022 未加载
ameliusabout 4 years ago
Looks nice. Perhaps a next step could be an ncurses program that allows you to fold&#x2F;unfold the trees at arbitrary places, and select entries to reveal their full path (useful for copy+paste).
roydivisionabout 4 years ago
I find I think about things a lot in tree structures, documentation, todo lists, technical information. I’m really keen to give this a go in my work. Thanks!
densekernelabout 4 years ago
What a beautiful idea. Like the application of quick analysis of ls or logs. Although now we are typically outputting JSON and collecting for Kibana.
评论 #26633716 未加载
kazinatorabout 4 years ago
<p><pre><code> $ find &#x2F;etc&#x2F;network | .&#x2F;frangi.tl etc: network: if-post-down.d: wireless-tools wpasupplicant avahi-daemon if-down.d: resolvconf wpasupplicant avahi-autoipd interfaces.d interfaces if-pre-up.d: wireless-tools wpasupplicant ethtool if-up.d: ntpdate wpasupplicant 000resolvconf openssh-server ethtool avahi-autoipd slrn avahi-daemon $ find &#x2F;etc&#x2F;network | .&#x2F;frangi-cheat.tl &#x2F;etc&#x2F;network &#x2F;if-post-down.d &#x2F;wireless-tools &#x2F;wpasupplicant &#x2F;avahi-daemon &#x2F;if-down.d &#x2F;resolvconf &#x2F;wpasupplicant &#x2F;avahi-autoipd &#x2F;interfaces.d &#x2F;interfaces &#x2F;if-pre-up.d &#x2F;wireless-tools &#x2F;wpasupplicant &#x2F;ethtool &#x2F;if-up.d &#x2F;ntpdate &#x2F;wpasupplicant &#x2F;000resolvconf &#x2F;openssh-server &#x2F;ethtool &#x2F;avahi-autoipd &#x2F;slrn &#x2F;avahi-daemon $ cat frangi-cheat.tl #!&#x2F;usr&#x2F;bin&#x2F;env txr (let (old-path) (whilet ((line (get-line))) (whenlet ((path (tok #&#x2F;[^\&#x2F;]*&#x2F; line)) (canon `@{path &quot;&#x2F;&quot;}`) (pos (mismatch path old-path))) (let ((cpos (max 0 (+ pos -1 [sum [path 0..pos] len])))) (put-line `@{&quot;&quot; cpos}@{canon [cpos..:]}`)) (set old-path path)))) $ cat frangi.tl #!&#x2F;usr&#x2F;bin&#x2F;env txr (defstruct (node name) list-builder name (:method equal (me) me.name) (:method ensure-child (me child-name) (let ((children me.(get))) (or (find child-name me.(get)) (let ((new-child (new (node child-name)))) me.(add new-child) new-child)))) (:method print (me stream : pretty-p) (let* ((old-im (set-indent-mode stream indent-code)) (old-id (get-indent stream)) (children me.(get)) (is-bottom (none children .(get)))) (unwind-protect (cond (children (put-line `@{me.name}:` stream) (set-indent stream (+ old-id 4)) [mapdo (op print @1 stream) children] (when is-bottom (put-char #\newline stream))) (t (put-string `@{me.name} `) stream)) (set-indent-mode stream old-im) (set-indent stream old-id))))) (let ((supernode (new (node :root)))) (whilet ((line (get-line))) (let ((path (tok #&#x2F;[^\&#x2F;]+&#x2F; line)) (node supernode)) (each ((comp path)) (set node node.(ensure-child comp))))) (each ((top-child supernode.(get))) (pprinl top-child)))</code></pre>
评论 #26627884 未加载
shipitabout 4 years ago
Exceptional!<p>I am a heavy user for `find &lt;&gt; | xargs grep` -- this makes my life so much sweeter. Thank you @birchb!
jedbergabout 4 years ago
It&#x27;s like super enhanced tree command! Very cool!
kevmoo1about 4 years ago
Super cool, yo! Very unix – do one simple thing well.
lnenadabout 4 years ago
This looks awesome, great job, thanks for sharing.
dvirskyabout 4 years ago
This is a really wonderful idea! Thanks, OP.