4 ms·
I prefer sam [1]. Unlike sed, it's not Turing complete, but it is far more elegant to my taste - consider this example from the article: :loop N; s/\n[[:sp
by piekvorst 7mo ago
I prefer sam [1]. Unlike sed, it's not Turing complete, but it is far more elegant to my taste - consider this example from the article:
:loop N; s/\n[[:space:]]\+/ /g; t loop; p
In sam, the equivalent is:
x/(.+\n)*/ x/\n */ c/ /
It reads like this: loop over paragraphs of non-empty lines, loop over newline followed by spaces, replace with a single space. It's surprisingly close to SQL in its eloquence.
Another example:
N; h; s/\n/->/g ;p; g; D
In sam, an equivalent would be
{
1,$-2 x/./ {
a/->/
/./ t .
}
$-1 d
}
Again, it's readable from top to bottom: from the first line to the second from the end, loop over each symbol, put "->" after it and copy the next symbol next to it; delete the last line.
Let's see how far we can get. Another example:
N; h; s/\n/->/g; p; G; D
In sam, an equivalent would be:
{
d
1,$-2 x/./ {
1,/./ x/.|\n/ {
g/./ t $
g/\n/ $ c/->/
}
$ c/\n/
}
}
It reads like this: delete the whole thing; from the first line to the second from the end, loop over each character; on each iteration, from the first line to the next character, run an inner loop over each character or newline; if it's a character, put it at the end; otherwise, put "->" at the end; once the inner loop is done, put a newline at the end.
The final example from the post is too long to have it here (15 lines). Here's just the sam equivalent for it:
x/(.+\n)+|\n+/ {
g/./ x/\n/ c/ /
v/./ c/\n/
}
It reads like this: loop over paragraphs of non-empty lines or sequences of newline characters; if it has any symbol (that is, it's a paragraph), replace each newline symbol with a space; if it doesn't have a symbol (that is, it's a sequence of newline symbols), replace it with a single newline.
What I have learned from this is that a tool with limited but well-chosen primitives is more convenient than a universal state machine.
(My examples may not be the exact same algorithms, since I do not understand (or need) sed concepts, but they do produce the same output.)
[1]: https://9p.io/sys/doc/sam/sam.html https://9p.io/sys/doc/sam/sam.html
- sanjayjc 7mo agoThat looks interesting. I thought sam was an editor (which I've only read about, never used.) Good to see it can be used on the command line. Is there a port to Apple silicon?
- piekvorst 7mo agoYes, sam can be used on the command line with ssam [1]. It's specific to plan9port [2]. In the original Plan 9, ssam wasn't included because Rob Pike didn't want to give up the X command that handles multiple files [3]: I find the X command extremely powerful, and can't see any way to have a streaming implementation that will look at multiple files simultaneously. > Is there a port to Apple silicon? plan9port works on it. It compiled without any errors on my Apple Silicon Mac. [1]: https://9fans.github.io/plan9port/man/man1/ssam.html https://9fans.github.io/plan9port/man/man1/ssam.html [2]: https://9fans.github.io/plan9port https://9fans.github.io/plan9port [3]: https://9fans.topicbox.com/groups/9fans/Tdf6095a105816f01-M34fec34ae4efe1a3b47f49de/9fans-re-n-n-n-to-n-n https://9fans.topicbox.com/groups/9fans/Tdf6095a105816f01-M3...
- jlp__inf 7mo agoThanks for sharing this, I’m learning a lot from it. So if I understand correctly, it’s selection-based, right? You first select a region, and then you can apply further selections inside it? So you kind of build nested selections to match exactly what you want (almost like a conditional tree). And then you apply operations on the current selection For example substitution with something like c/PATTERN/, is that correct?
- piekvorst 7mo agoThat's exactly right. A few unmentioned details: . The dot (".") never matches newlines, which keeps line-oriented idioms from accidentally spanning newlines [1] . Changes must be sequential and non-overlapping (that's why I deleted the whole thing before processing in the third example). . Sam matches only the original input, not past changes. . Addresses (expressions before commands) select a single range, x commands select multiple ranges and loop over it. [1]: https://p9f.org/sys/doc/sam/sam.html https://p9f.org/sys/doc/sam/sam.html, Regular expressions
- jlp__inf 7mo agoThanks for those complementary informations. Also, while i'm learning it, maybe that the sam traduction for the first file would be simpler, like: ,x/\n +/ c/ /
- jlp__inf 7mo agoAlso, i managed to, i think simplify the second example to: 1,$-2 x/./ { a/->/ /./ t . } 1,$-2 { p } q Which taught me a lot, because at first, i did not understand why we would stop at last line - 2 ($ - 2), but in fact yeah last line is the very last "\n", that is why we stop at $ - 2 to not do E->weird. I'm starting to truly love sam
- jlp__inf 7mo agoand yess, g/PATTERN/ and /v/PATTERN/ are supzr powerful, creating branch conditions based on wether or not they (do not)match a PATTERN. based on what you wrote: i just add trailing \n normalization at the end , x/(.+\n)+|\n+/ { g/./ x/\n/ c/ / v/./ c/\n/ } $ a/\n/ , x/\n+$/ c/\n/ w file_out.txt q