Re: GNU sed manual describes t/T a little wrong?

"Paolo Bonzini [email protected] [sed-users]" <[email protected]>
Newsgroups gmane.editors.sed.user
Message-ID <[email protected]>
On 28/05/2015 03:42, [email protected] [sed-users] wrote:
> I received an email from Anders Granlund (in Sweden) pointing out a
> subtle error in the GNU sed manual definitions of t and T (T is a GNU
> extension). I've explored this and think Anders is right.

I agree with your reasoning.  Adding the GNU sed maintainer.

Paolo

> "Branch to label only if there has been a successful substitution
> since the last input line was read or conditional branch was taken." is
> the current wording in the GNU sed manual for t.
> 
> "Branch to label only if there has been a successful substitution
> since the last input line was read or conditional branch was run." seems
> to me a more correct wording.
> 
> The current definition for t and T ends with "taken" (ie, branch
> taken). The suggested change ends with "run" (ie, t or T run). By
> "conditional branch", it means t or T, and "branch was taken" means t or
> T branched.
> 
> The original description of sed (from 1970's) says: "The t function
> tests whether any successful substitutions have been made on the current
> input line; if so, it branches to 'label'; if not, it does nothing. The
> flag which indicates that a successful substitution has been executed is
> reset by: 1) reading a new input line, or 2) executing a t function."
> The phrase "executing a t function" seems consistent to me with "t was
> run", not "branch was taken". So that is one line of reasoning that the
> GNU sed manual seems in error.
> 
> The other line of reasoning is to look at what sed does. Here is a
> test script I made up to look at cases that might arise:
> 
> $ cat test1.sh
> echo "Input to sed is always the string 'old'" 
> echo "----------------------------------------------------------" 
> echo "Cases 1-4 are easy, as flag does not get reset" 
> echo "----------------------------------------------------------" 
> echo "Case 1. s works, sets flag, so t branches past d" 
> echo "Case 1. Point is that t branches if flag is set" 
> echo old | sed "s/old/new/; t; d" 
> echo "----------------------------------------------------------" 
> echo "Case 2. s fails, flag not set, so T branches past d" 
> echo "Case 2. Point is that T branches if flag not set" 
> echo old | sed "s/---/new/; T; d" 
> echo "----------------------------------------------------------" 
> echo "Case 3. s fails, flag not set, so t does not branch" 
> echo "Case 3. Point is that t does not branch if flag not set" 
> echo old | sed "s/---/new/; t; d" 
> echo "----------------------------------------------------------" 
> echo "Case 4. s works, sets flag, so T does not branch" 
> echo "Case 4. Point is that T does not branch if flag set" 
> echo old | sed "s/old/new/; T; d" 
> echo "----------------------------------------------------------" 
> echo "Cases 5-8 see if flag gets reset after s works" 
> echo "----------------------------------------------------------" 
> echo "Case 6. s works, tx branches, flag reset, t fails" 
> echo "Case 6. Point is that t flag is reset if t branches" 
> echo old | sed "s/old/new/; tx; d; :x t; l" 
> echo "----------------------------------------------------------" 
> echo "Case 6. s works, tx branches, flag reset, T branches" 
> echo "Case 6. Point is that T flag is reset if t branches" 
> echo old | sed "s/old/new/; tx; d; :x T; l" 
> echo "----------------------------------------------------------" 
> echo "Case 7. s works, Tx fails, flag reset, T branches" 
> echo "Case 7. Point is that T flag is reset if T fails" 
> echo old | sed "s/old/new/; Tx; l; :x T; d" 
> echo "----------------------------------------------------------" 
> echo "Case 8. s works, Tx fails, flag reset, t fails" 
> echo "Case 8. Point is that t flag is reset if T fails" 
> echo old | sed "s/old/new/; Tx; l; :x t; d" 
> echo "----------------------------------------------------------" 
> echo "Cases 9-10 see if flag gets reset by s just running"
> echo "----------------------------------------------------------"
> echo "Case 9. s1 works, s2 fails, but t still branches due to s1"
> echo "Case 9. Point is that flag is not reset by s just running"
> echo old | sed "s/old/new/; s/---/new/; t; d"
> echo "----------------------------------------------------------"
> echo "Case 10. s1 works, s2 fails, but T still fails due to s1"
> echo "Case 10. Point is that flag is not reset by s just running"
> echo old | sed "s/old/new/; s/---/new/; T; d"
> echo "----------------------------------------------------------"
> 
> Here is what results:
> 
> $ ./test1.sh
> Input to sed is always the string 'old'
> ----------------------------------------------------------
> Cases 1-4 are easy, as flag does not get reset
> ----------------------------------------------------------
> Case 1. s works, sets flag, so t branches past d
> Case 1. Point is that t branches if flag is set
> new
> ----------------------------------------------------------
> Case 2. s fails, flag not set, so T branches past d
> Case 2. Point is that T branches if flag not set
> old
> ----------------------------------------------------------
> Case 3. s fails, flag not set, so t does not branch
> Case 3. Point is that t does not branch if flag not set
> ----------------------------------------------------------
> Case 4. s works, sets flag, so T does not branch
> Case 4. Point is that T does not branch if flag set
> ----------------------------------------------------------
> Cases 5-8 see if flag gets reset after s works
> ----------------------------------------------------------
> Case 6. s works, tx branches, flag reset, t fails
> Case 6. Point is that t flag is reset if t branches
> new$
> new
> ----------------------------------------------------------
> Case 6. s works, tx branches, flag reset, T branches
> Case 6. Point is that T flag is reset if t branches
> new
> ----------------------------------------------------------
> Case 7. s works, Tx fails, flag reset, T branches
> Case 7. Point is that T flag is reset if T fails
> new$
> new
> ----------------------------------------------------------
> Case 8. s works, Tx fails, flag reset, t fails
> Case 8. Point is that t flag is reset if T fails
> new$
> ----------------------------------------------------------
> Cases 9-10 see if flag gets reset by s just running
> ----------------------------------------------------------
> Case 9. s1 works, s2 fails, but t still branches due to s1
> Case 9. Point is that flag is not reset by s just running
> new
> ----------------------------------------------------------
> Case 10. s1 works, s2 fails, but T still fails due to s1
> Case 10. Point is that flag is not reset by s just running
> ----------------------------------------------------------
> 
> The key cases are #7 and #8. In both cases, s substituted, so T did
> not branch. According to the current GNU sed manual, branching is
> required to reset the flag. But the flag was reset, so T branches next
> time it appears, and t does not branch next time it appears. Merely
> running t or T, even if no branch, is enough to reset the flag.
> 
> I don't think this is a big deal. It seems rather obscure, something
> that had never crossed my mind until Anders found it. I would always put
> t or T immediately after the s command, so cases 7 and 8 would rarely or
> never occur in practice. It seems like asking for trouble to have
> multiple t/T commands scattered about. But who knows? Maybe this might
> come up in some games that get programmed in complex sed scripts.
> 
> Whether this is good style or not, the point is the current wording
> seems incorrect. If the manual is incorrect, I hope it can get fixed. If
> the current wording is OK, I'd be interested to hear what Anders and I
> missed.
> 
> Thanks,
> Daniel
> 
> 
> ------------------------------------
> Posted by: [email protected]
> ------------------------------------
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.