Last active
March 2, 2025 20:59
-
-
Save emanuele6/d846879d025fbbac674b676df6682b70 to your computer and use it in GitHub Desktop.
POSIX ed script that prepends line numbers to the lines of a file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1s/^/1 / | |
2,$g/^/-t -\ | |
s/ .*//\ | |
s/^9*$/0&/\ | |
t .\ | |
s/^.*[^9]\(9*\)$/\1 /\ | |
s/9/0/g\ | |
-s/9*$//\ | |
s/8$/9/\ | |
s/7$/8/\ | |
s/6$/7/\ | |
s/5$/6/\ | |
s/4$/5/\ | |
s/3$/4/\ | |
s/2$/3/\ | |
s/1$/2/\ | |
s/0$/1/\ | |
.,+2j | |
w | |
q |
Thanks a lot, this is genius. I love it.
Thank you for the script and for the explanation.
i couldn't understand it specifically because of the 9 replaced by 0 part and copying another line and the effect it had in the incrementation process.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@dmbarrad Hello.
(example text file;
>
is the position of the cursor)The first command is
1s/^/1 /
adds "1
" in front of the first lineThen the second command is a
2,$g/^/...
command that runs a sequenceof commands on all the other lines:
At the start of the first iteration, the cursor is at line 2:
First,
-t -
copies the previous line, on the line before the currentline:
Then
s/ .*//
removes everything after the first space on the currentline, leaving only the line number:
Then
s/^9*$/0&/
prefixes a0
to the number if it is all9
s, (e.g.9
=>09
, or99
=>099
); in this case it does nothing.t .
adds a copy of the current line after the current line (and movesthe cursor there)
s/^.*[^9]\(9*\)$/\1 /
(note that all lines can match this regexpbecause a
0
is always prefixed to lines with only9
earlier) replacesthe entire line with just the 9s at the end of the line followed by a
space (e.g.
129499
=>99
); in this case it replaces1
with(n.b. the line is not empty, it contains a space):
s/9/0/g
replaces all those9
s with0
s, in this case it doesnothing.
-s/9*$//
moves the cursor back to the previous line, and removes allthe
9
s at the end of the line, if any (e.g.1099
=>10
); in thiscase it just moves the cursor back:
s/8$/9/
,s/7$/8/
,s/6$/7/
,s/5$/6/
,s/4$/5/
,s/3$/4/
,s/2$/3/
,s/1$/2/
, ands/0$/1/
in sequence basically increment thelast digit of the line by 1; that is how it gets
2
from the1
of theprevious line:
Finally
.,+2j
joins the current line with the following two linesending up with:
This sequence is then repeated for all lines in the file by the
g
command:
And in the end all the lines are prefixed with their line number.
To show a more interesting case:
-t -
:s/ .*//
:s/^9*$/0&/
(nothing)t .
s/^.*[^9]\(9*\)$/\1 /
: (n.b. there is a space at the end of the line)s/9/0/g
:-s/9*$//
:s/8$/9/
s/7$/8/
s/6$/7/
s/5$/6/
s/4$/5/
s/3$/4/
(nothing)s/2$/3/
:s/1$/2/
s/0$/1/
(nothing).,+2j
:Another interesting case:
-t -
:s/ .*//
:s/^9*$/0&/
:t .
:s/^.*[^9]\(9*\)$/\1 /
: (n.b. there is a space at the end of the line)s/9/0/g
:-s/9*$//
:s/8$/9/
s/7$/8/
s/6$/7/
s/5$/6/
s/4$/5/
s/3$/4/
s/2$/3/
s/1$/2/
(nothing)s/0$/1/
:.,+2j
: