Explain this behavior of sed conditional branching

I have the following (gnu) sedscript that is designed to parse another sed script and output individual commands on a separate line.

In words, this script should put a newline character after each semicolon ;, except for the semicolons that are inside the match or wildcard command.

Sed script :

#!/bin/sed -rf

# IDEA:
# replace ';' by ';\n' except when it inside a match expression or subst. expression.

# Ignored patterns:
/^#/b   # commented lines
/^$/b   # empty lines
# anything in a single line, without semicolon except at the end
/^[^\n;]*;?$/b

# Processed patterns (put on separate lines):
# Any match preceding a semicolon, or the end of the line, or a substitution
s_/^[^/]+/[^;s]*;?_&\n_;      t printtopline
s/^\\(.)[^\1]+\1[^;s]*;?/&\n/;t printtopline
# Any substitution (TODO)

# Any other command, separated by semicolon
s/\;/\;\n/; t printtopline;

:printtopline
P;D;  # print top line, delete it, start new cycle

For example, I tested it with the following file (actually adapted from @ctac_'s answer to one of my previous sed questions):

Input file:

#!/bin/sed -f

#/^>/N;

:A;
/\n>/!{s/\n/ /;N;bA};  # join next line if not a sequence label
#h;
#s/\(.*\)\n.*/\1/p;
s/^>//g;P

#x;
#s/.*\n//;
D
bA;

Output

The above script creates the correct output, for example, the line /\n>/!{s/\n/ /;N;bA}; # join next line if not a sequence labelbecomes:

/\n>/!{s/\n/ /;
N;
bA};
  # join next line if not a sequence label

Question

, , script :

s/\;/\;\n/; t printtopline;

:printtopline

, t printtopline . , , , , :printtopline.

, t b, script :

/\n>/!{s/\n/ /;
N;bA};  # join next line if not a sequence label

info sed, t:

't LABEL'
     Branch to LABEL only if there has been a successful 's'ubstitution
     since the last input line was read or conditional branch was taken.
     The LABEL may be omitted, in which case the next cycle is started.

t , b?

+4
2

:

, .

.. t

  • .

, .

/\n>/!{s/\n/ /;
N;bA};  # join next line if not a sequence label

, P;D;. P , D .

N;bA};  # join next line if not a sequence label

, - . ; D .

( , ), :

s_/^[^/]+/[^;s]*;?_&\n_;      t printtopline

( /^). t s; .

, /\n>/!{s/\n/ /;N;bA};.

s/\;/\;\n/; t printtopline;

:printtopline

. , t . , .

(b ):

s/\;/\;\n/; b printtopline;

:printtopline

, t s_/^[^/]+/[^;s]*;?_&\n_; t printtopline "" s/\;/\;\n/; , P;D;. ,

N;bA};  # join next line if not a sequence label

.

: t - , , t, . t s t.

+4

1 - P; D; .

: sed 's/;/;\n/' sed 's/;/;\n/; P;D;'.

-:

$ sed 's/;/;\n/' <<< 'one;two;three;four'
one;
two;three;four

:

$ sed 's/;/;\n/; P;D;' <<< 'one;two;three;four'
one;
two;
three;
four

? .

first ;. , g s: sed 's/;/;\n/g'.

second :

  • sed 's/;/;\n/; - , - . one;two;three;four, - one\ntwo;three;four.
  • P; -
    • : " ".
    • , - one. : one\ntwo;three;four
  • D; -

    • : " , , d    .      , ."

    • - one\ntwo;three;four. D; one\n . : two;three;four.

    • sed 's/;/;\n/; - : two\nthree;four, P; - print two, : two\nthree;four, D; - two\n, : three;four. ..

2 - .

sed :

s , replaced true:

/* We found a match, set the 'replaced' flag. */
          replaced = true;

t, replaced true. false:

case 't': 
    if (replaced)
    {
        replaced = false;

, first, s/\;/\;\n/; t printtopline; , replaced true. t replaced false.

t - s/\;/\;\n/; , replaced true.

, D. , t - s_/^[^/]+/[^;s]*;?_&\n_; t printtopline, replaced, , true :printtopline, .

, P;D; .

0

Source: https://habr.com/ru/post/1688315/


All Articles