Sujet : Re: a sed question
De : janis_papanagnou+ng (at) *nospam* hotmail.com (Janis Papanagnou)
Groupes : comp.unix.shellDate : 21. Dec 2024, 16:19:48
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <vk6mam$3lsj$1@dont-email.me>
References : 1 2 3
User-Agent : Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0
On 21.12.2024 13:17, Salvador Mirzo wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
On 18.12.2024 20:46, Salvador Mirzo wrote:
(*) Summary
>
I wrote a sed script that makes a line replacement after it finds the
right spot. So far so good. Then I added quit command after the
change, but the quit does not seem to take effect---violating my
expectation. I'll appreciate any help on understanding what's going on.
>
First (before I forget it) change your string comparison '<' to the
numerical comparison operator '-lt' as in: test $# -lt 2 && usage
Otherwise, if you get used to using the wrong operator, you may get
subtle errors in future if you continue that habit.
Changed. Why is it the wrong operator? It seems it's not the standard
one---checking just now on the POSIX.1 spec. I think I just tried it
out and given it worked as expected, I didn't think of checking it. I'm
new to the whole thing.
If you're new be very cautious with Shell; it looks easy to handle
but has a lot subtleties!
You have two sets of comparison operators in Unix shell; strangely
the ones we'd expect to compare numerically (=, !=, <, <=, >, >=)
instead do string comparisons (order of characters). And for the
numeric comparison there's other (-eq, -ne, -lt, -le, -gt, -ge)
operators.
The difference can be observed when comparing numbers in strings
like, say, 11 and 2.
[ 11 -lt 2 ] # returns false (numeric 11 is greater than 2)
[ 11 '<' 2 ] # returns true (string 11 comes before string 2)
The first is a comparison [of strings] interpreted as a numeric
entity, the second is a comparison [of strings] as a string with
lexicographic ordering.
Note also that in modern shells there's also $((...)) and ((...))
(arithmetic expansion and the [non-standard] arithmetic command)
available which support a syntax that is less surprising; e.g.
$ echo $(( 11 < 2 ))
$ (( 11 < 2 )) && ...
(without quoted operator and with numerical semantics).
Also note that using $* may not work correctly (e.g. depending on
filenames [containing spaces] used). The safe form is a quoted "$@"
I learned something here.
The point with spaces in filenames is also something elementary
to know; that's why the "$@" needs quoting (and quoted variables
is the rule of thumb for variable expansions [for most cases]).
[snip code]
(Then I was tempted to make a similar comment as Kenny. But...)
I'm studying and I often go back to the past to see what life was I
like. I initially tried to solve the problem with /ed/, but did not
find a way to insert a string coming from the a shell script's cmdline.
Then I thought that /sed/ was there to make /ed/ more scriptable.
I very very rarely use 'ed' but I recall to have used it feeding
input from stdin to it, so it is in principle possible to also
feed in expanded shell variables as part of the 'ed' input.
WRT your question I'd be interested to understand more about the
intention of your original question...
The intention is mostly in the paragraph above, but the way I study is
to put things in real-world practice as much as possible. (When I
realize the solution is indeed too old to make sense, I replace it.
Otherwise I stick with it.) I have a literate programming file that
contains a chunk that's the version of the program I'm writing. So when
you ask the program its version, the information is included in the
executable, an idea which I like. I get the version with a git command
such as
As previously mentioned, 'sed' might not be the best choice for
developing such scripts; you might want to consider to learn 'awk'.
$ git log --oneline | head -1 | awk '{print $1}'
2566d31
With Awk you don't need 'head', it can be done like this
$ git log --oneline | awk 'NR==1 {print $1}'
(For long input files you may want an early exit
...| awk 'NR==1 { print $1 ; exit(0) }'
but that just as an aside.)
So I wanted to include such string in the literate programming file. At
first I wrote a solution in the programming language I'm using, but I
remember seeing many older software using sed for something like that,
so I decided to study sed a bit. I read the sed part of Dale Dougherty
and Arnold Robbins's book "sed & awk", second edition, and I thought sed
was quite neat and sensible. What I'm noticing now is that there are
too many different sed behavior out there to make it sensible to use.
UNIX systems as a whole are like that, so I'm used to reminding myself
of using the common subset of everything. Perhaps the common subset of
sed is too small. If I have to use it just for search and replace, then
perhaps it's not really worth it.
Awk has a powerful large common subset and its base is standardized.
(GNU Awk as a prevalent variant has a couple interesting extensions.)
Since your book covers Awk you should have a look into it. (Arnold
has also another book solely on Awk published, the GNU Awk Manual,
which is also available online.)
I mean if you don't trust your 'sed' command just pipe it though
'less'; there's no need to change the 'sed' program just for that.
>
Personally I'd try whether it works (by adding "something" before
and also after the desired place in your sample.txt to be sure the
other occurrences were not changed), and then just call
>
sed -e '/<<Release>>=/,+1s/something/sth else/' sample.txt
>
to see it working.
Thanks for the excellent instruction!
You're welcome.
Janis