I try to understand the following complex sed command logic
instructions given here [1]:
[...]
But the logic contained in the sed code snippet above is still
obscure to me. Any hints?
OTOH, the final result achieved by the sed workflow does seem so
trivial. Why do they still insist on providing such an ancient
sed-based solution?
On 11.12.2021 12:30, hongy...@gmail.com wrote:
I try to understand the following complex sed command logic
instructions given here [1]:
[...]
But the logic contained in the sed code snippet above is stillGet the sed manual and identify the used commands. Or formulate
obscure to me. Any hints?
the simple algorithm yourself informally and try to identify the
building blocks in the sed code.
OTOH, the final result achieved by the sed workflow does seem soMaybe it's code from the 1980's?
trivial. Why do they still insist on providing such an ancient
sed-based solution?
Maybe the programmer is used to that tool?
Maybe the programmer doesn't know any better tool?
Who knows?
But I see no one insisting in anything.
Though, for simple tasks you can always write your own version,
and use a language that is or appears to you as less cryptic.
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
(or replace the 1 by {print} to make it less cryptic). For many
folks that's easier to read because syntax is similar to the C
language and its language family.
But the code is just a quick shot; you may want your program to
also handle empty files, or files that have just comments and
no data lines (that triggers the condition), and maybe use GNU
Awk with the in-place editing feature that is also used in the
sed call.
Janis
On 11.12.2021 12:30, hongy...@gmail.com wrote:
I try to understand the following complex sed command logic
instructions given here [1]:
[...]
But the logic contained in the sed code snippet above is stillGet the sed manual and identify the used commands. Or formulate
obscure to me. Any hints?
the simple algorithm yourself informally and try to identify the
building blocks in the sed code.
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:
On 11.12.2021 12:30, hongy...@gmail.com wrote:
I try to understand the following complex sed command logic
instructions given here [1]:
[...]
I try to decrypt it as follows, please correct me if I'm wrong:But the logic contained in the sed code snippet above is stillGet the sed manual and identify the used commands. Or formulate
obscure to me. Any hints?
the simple algorithm yourself informally and try to identify the
building blocks in the sed code.
sed -Ei
use extended regular expressions in the script
and
edit files in place
-e
add the script to the commands to be executed
'
Begin the script
/^([^#]|$)/
Anchor lines that is empty or does not start with #
{
Begin a block of commands
a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
Append text, which has each embedded newline preceded by a backslash.
a \
' -e ':a' -e '$!{n;ba};
Failed to figure out the above obscure code block.
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:
On 11.12.2021 12:30, hongy...@gmail.com wrote:
I try to understand the following complex sed command logicGet the sed manual and identify the used commands. Or formulate
instructions given here [1]:
[...]
But the logic contained in the sed code snippet above is still
obscure to me. Any hints?
the simple algorithm yourself informally and try to identify the
building blocks in the sed code.
Maybe it's code from the 1980's?
OTOH, the final result achieved by the sed workflow does seem so
trivial. Why do they still insist on providing such an ancient
sed-based solution?
Maybe the programmer is used to that tool?
Maybe the programmer doesn't know any better tool?
Who knows?
But I see no one insisting in anything.
Though, for simple tasks you can always write your own version,
and use a language that is or appears to you as less cryptic.
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
I try to debug/understand your above code as follows:
$ awk '!/^#/ && !f++ { print "..." } ; {print $0, f, f++}' .profile | head -3 #!/usr/bin/env bash 0
2 2
# To do: 3 3
$ awk '!/^#/ && !f++ { print "..." } ; {print $0, f}' .profile | head -3 #!/usr/bin/env bash
...
1
As you can see, when I try to print the value of `f++`, the desired modification results will disappear. This should mean that the variable was altered as it was printed, which makes debugging in this form impossible.
(or replace the 1 by {print} to make it less cryptic). For many
folks that's easier to read because syntax is similar to the C
language and its language family.
But the code is just a quick shot; you may want your program to
also handle empty files, or files that have just comments and
no data lines (that triggers the condition), and maybe use GNU
Awk with the in-place editing feature that is also used in the
sed call.
Janis
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
The above code will add the stuff at the very beginning of the
script if occasionally the shebang line is not the first line:
$ cat test.sh
#!/usr/bin/env bash
echo 'hello world.'
$ ./test.sh
hello world.
$ awk '!/^#/ && !f++ { print "..."} ; {print $0}' test.sh
...
#!/usr/bin/env bash
echo 'hello world.'
HZ
On 12.12.2021 07:32, hongy...@gmail.com wrote:
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
The above code will add the stuff at the very beginning of the1. The posted requirements had been
script if occasionally the shebang line is not the first line:
# the sed invocation inserts the lines at the start of the file
# after any initial comment lines
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
If you happen to have other requirements adjust the condition.
(Don't expect that we can read your mind from that distance.)
You want to consider [initial] blank lines similar to comments,
for example?
!(/^#/||!NF) && !f++ ...
On 12.12.2021 01:42, hongy...@gmail.com wrote:
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:
On 11.12.2021 12:30, hongy...@gmail.com wrote:
I try to understand the following complex sed command logicGet the sed manual and identify the used commands. Or formulate
instructions given here [1]:
[...]
But the logic contained in the sed code snippet above is still
obscure to me. Any hints?
the simple algorithm yourself informally and try to identify the
building blocks in the sed code.
Maybe it's code from the 1980's?
OTOH, the final result achieved by the sed workflow does seem so
trivial. Why do they still insist on providing such an ancient
sed-based solution?
Maybe the programmer is used to that tool?
Maybe the programmer doesn't know any better tool?
Who knows?
But I see no one insisting in anything.
Though, for simple tasks you can always write your own version,
and use a language that is or appears to you as less cryptic.
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
I try to debug/understand your above code as follows:Understand how f++ works - in *any* of the many languages that support
it - before you try to "debug".
GNU Awk has a debugger that makes it unnecessary in practice to add own [possibly or likely wrong] code.
On Sunday, December 12, 2021 at 7:57:26 PM UTC+8, Janis Papanagnou wrote:
GNU Awk has a debugger that makes it unnecessary in practice to add own
[possibly or likely wrong] code.
But this way it only supports running script from file, instead of the in-line ones from stdin:
$ awk --help |grep -i debug
-D[file] --debug[=file]
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote:
On 12.12.2021 07:32, hongy...@gmail.com wrote:
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote: >>>> I'd use Awk, for example, probably something like1. The posted requirements had been
awk '!/^#/ && !f++ { print "..." } ; 1'
The above code will add the stuff at the very beginning of the
script if occasionally the shebang line is not the first line:
# the sed invocation inserts the lines at the start of the file
# after any initial comment lines
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the empty line preceding it, the script still works as expected.
{
Begin a block of commands
a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
Append text, which has each embedded newline preceded by a backslash.
a \
' -e ':a' -e '$!{n;ba};
Failed to figure out the above obscure code block.
Especially, there are two '-e' constructs embedded in outer '-e'
construct, which is very confusing for me.
sed -Ei -e '/^([^#]|$)/ {a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
a \
' -e ':a' -e '$!{n;ba};}' ~/.profile
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote:[...]
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the
empty line preceding it, the script still works as expected.
You want to understand what the program does, don't you?
So put it in a file to use the debugger. What is your problem.
"hongy...@gmail.com" <hongy...@gmail.com> writes:
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote:[...]
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the empty line preceding it, the script still works as expected.No, a shebang line must be on the first line, and the "#!" must be the
first two characters of the first line, or it will be ignored (which, depending on the interpreter, usually means it's treated as a comment).
If a script has no shebang, the way it's executed depends on how you
invoke it. If you invoke it from bash, it executes it as a bash script.
If you invoke it by calling system(script_name), it uses /bin/sh.
On Sunday, December 12, 2021 at 11:18:02 PM UTC+8, Janis Papanagnou wrote:
On 12.12.2021 13:15, hongy...@gmail.com wrote:
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote:
On 12.12.2021 07:32, hongy...@gmail.com wrote:
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:1. The posted requirements had been
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
The above code will add the stuff at the very beginning of the
script if occasionally the shebang line is not the first line:
# the sed invocation inserts the lines at the start of the file
# after any initial comment lines
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the empty line preceding it, the script still works as expected.I have the impression that you still don't understand the mechanics.
Try this code (first line empty) and you see that the #! is ineffective. ---snip---
#!/usr/bin/awk -fYes. The above code will fail as follows:
BEGIN { print "Hi" }
---snip---
$ ./test.awk
./test.awk: line 3: BEGIN: command not found
But I still don't understand why the following example works:
$ cat test.sh
#!/bin/bash
echo 'Hello.'
$ ./test.sh
Hello.
On 12.12.2021 13:15, hongy...@gmail.com wrote:
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote:
On 12.12.2021 07:32, hongy...@gmail.com wrote:
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:1. The posted requirements had been
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
The above code will add the stuff at the very beginning of the
script if occasionally the shebang line is not the first line:
# the sed invocation inserts the lines at the start of the file
# after any initial comment lines
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the empty line preceding it, the script still works as expected.I have the impression that you still don't understand the mechanics.
Try this code (first line empty) and you see that the #! is ineffective. ---snip---
#!/usr/bin/awk -f
BEGIN { print "Hi" }
---snip---
Or if you run a standard shell script with #!/usr/bin/bash with
some non-standard shell environment you will also get errors.
There are a couple conditions that must be fulfilled for a shebang
script to get that line become active as an interpreter directive.
The one we have been talking about here is that it must be the first
line in the file (no empty lines or anything).
Janis
On Monday, December 13, 2021 at 6:06:03 AM UTC+8, Keith Thompson wrote:
"hongy...@gmail.com" <hongy...@gmail.com> writes:
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote: >> [...]No, a shebang line must be on the first line, and the "#!" must be the
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the
empty line preceding it, the script still works as expected.
first two characters of the first line, or it will be ignored (which,
depending on the interpreter, usually means it's treated as a comment).
Where is this specification clearly stated?
No, there is no "embedded" -e construct. Re-read the original post:
sed -Ei -e '/^([^#]|$)/ {a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
a \
' -e ':a' -e '$!{n;ba};}' ~/.profile
The first -e is followed by an opening single quote ' so everything from there to the following closing single quote ' on the last line is one "script" to be executed. Then there is the second -e ':a' after that,
and finally the third -e script (also in single quotes). None are
embedded in the other. There are three consecutive script fragments.
Little details such as the placement of those single quotes are
crucially important in shell/sed/awk scripting. You must learn to
notice them and understand them!
From "man execve" ...
Interpreter scripts
An interpreter script is a text file that has execute permission enabled and whose first line is of the form:
#!interpreter [optional-arg]
On Sunday, December 12, 2021 at 11:18:02 PM UTC+8, Janis Papanagnou wrote:
On 12.12.2021 13:15, hongy...@gmail.com wrote:
On Sunday, December 12, 2021 at 7:52:02 PM UTC+8, Janis Papanagnou wrote: >> >> On 12.12.2021 07:32, hongy...@gmail.com wrote:I have the impression that you still don't understand the mechanics.
On Saturday, December 11, 2021 at 8:23:09 PM UTC+8, Janis Papanagnou wrote:1. The posted requirements had been
I'd use Awk, for example, probably something like
awk '!/^#/ && !f++ { print "..." } ; 1'
The above code will add the stuff at the very beginning of the
script if occasionally the shebang line is not the first line:
# the sed invocation inserts the lines at the start of the file
# after any initial comment lines
2. What do you expect from a shebang line that is _ineffective_;
because it is *not* on the first line?
But as you can see, even if shebang is not the first line, such as the empty line preceding it, the script still works as expected.
Try this code (first line empty) and you see that the #! is ineffective.
---snip---
#!/usr/bin/awk -f
BEGIN { print "Hi" }
---snip---
Yes. The above code will fail as follows:
$ ./test.awk
./test.awk: line 3: BEGIN: command not found
But I still don't understand why the following example works:Becase the system runs this file with bash, with the shebang interpreted
$ cat test.sh
#!/bin/bash
echo 'Hello.'
$ ./test.sh
Hello.
Or if you run a standard shell script with #!/usr/bin/bash with
some non-standard shell environment you will also get errors.
There are a couple conditions that must be fulfilled for a shebang
script to get that line become active as an interpreter directive.
The one we have been talking about here is that it must be the first
line in the file (no empty lines or anything).
Janis
On Sunday, December 12, 2021 at 11:18:02 PM UTC+8, Janis Papanagnou wrote:
Try this code (first line empty) and you see that the #! is ineffective.
---snip---
#!/usr/bin/awk -f
BEGIN { print "Hi" }
---snip---
Yes. The above code will fail as follows:
$ ./test.awk
./test.awk: line 3: BEGIN: command not found
But I still don't understand why the following example works:
$ cat test.sh
#!/bin/bash
echo 'Hello.'
$ ./test.sh
Hello.
On 13.12.2021 02:49, hongy...@gmail.com wrote:
On Sunday, December 12, 2021 at 11:18:02 PM UTC+8, Janis Papanagnou wrote:
Try this code (first line empty) and you see that the #! is ineffective. >> ---snip---
#!/usr/bin/awk -f
BEGIN { print "Hi" }
---snip---
Yes. The above code will fail as follows:
$ ./test.awk
./test.awk: line 3: BEGIN: command not found
But I still don't understand why the following example works:
For the same reason why that program also works without the #! line.
$ cat test.sh
#!/bin/bash
echo 'Hello.'
$ ./test.sh
Hello.
You may want to inform yourself more thoroughly by reading articles
about #!. Wikipedia - https://en.wikipedia.org/wiki/Shebang_(Unix) -
is a good start and incidentally answers also your question. If you
have specialized questions or want to know about some gory details
have a look into https://www.in-ulm.de/~mascheck/various/shebang/ .
On Monday, December 13, 2021 at 4:19:08 AM UTC+8, John-Paul Stewart wrote:
No, there is no "embedded" -e construct. Re-read the original post:
sed -Ei -e '/^([^#]|$)/ {a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
a \
' -e ':a' -e '$!{n;ba};}' ~/.profile
The first -e is followed by an opening single quote ' so everything from there to the following closing single quote ' on the last line is one "script" to be executed. Then there is the second -e ':a' after that,Ok. Let me try to understand the last two script fragments:
and finally the third -e script (also in single quotes). None are
embedded in the other. There are three consecutive script fragments.
-e ':a' -e '$!{n;ba};}'
:a Make label a for b command.
$ Match the last line.
! After the address (or address-range), and before the command, a ! may be inserted, which specifies
that the command shall only be executed if the address (or address-range) does not match.
{ Begin a block of commands (end with a }).
n N Read/append the next line of input into the pattern space.
b label
Branch to label; if label is omitted, branch to end of script.
; Is used to separate multiple sed commands, IIRC.
By putting all the above knowledge together, I still haven't figured out any clues
pertaining to the goal to be achieved here.
Little details such as the placement of those single quotes areThank you for pointing this out.
crucially important in shell/sed/awk scripting. You must learn to
notice them and understand them!
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 285 |
Nodes: | 16 (2 / 14) |
Uptime: | 67:46:32 |
Calls: | 6,488 |
Calls today: | 1 |
Files: | 12,096 |
Messages: | 5,275,268 |