Sed substitution possible with arithmetic involved?

前端 未结 4 1667
眼角桃花
眼角桃花 2020-12-16 21:18

File I need to modify contains the following:

block: 16, size: 16, start: 8, length: 4

I\'d like the file so that values for block<

4条回答
  •  独厮守ぢ
    2020-12-16 22:08

    (The right tool to do this is awk, but for the fun of a sed exercise...)

    It is possible in sed. After all, a multiplication by 2 is set of substitution of the last digit according to some simple rules:

    • 0 --> 0
    • 1 --> 2
    • 2 --> 4
    • 3 --> 6
    • ...
    • 8 --> 16
    • 9 --> 18

    To take care of the carry digit, each rules should be written twice.

    This sed script, that can be run with sed -f script, do the multiplication by 2 of all the numbers on the input lines:

    s/$/\n\n/
    :loop
    s/0\n1\n/\n\n1/;t loop
    s/0\n\n/\n\n0/;t loop
    s/1\n1\n/\n\n3/;t loop
    s/1\n\n/\n\n2/;t loop
    s/2\n1\n/\n\n5/;t loop
    s/2\n\n/\n\n4/;t loop
    s/3\n1\n/\n\n7/;t loop
    s/3\n\n/\n\n6/;t loop
    s/4\n1\n/\n\n9/;t loop
    s/4\n\n/\n\n8/;t loop
    s/5\n1\n/\n1\n1/;t loop
    s/5\n\n/\n1\n0/;t loop
    s/6\n1\n/\n1\n3/;t loop
    s/6\n\n/\n1\n2/;t loop
    s/7\n1\n/\n1\n5/;t loop
    s/7\n\n/\n1\n4/;t loop
    s/8\n1\n/\n1\n7/;t loop
    s/8\n\n/\n1\n6/;t loop
    s/9\n1\n/\n1\n9/;t loop
    s/9\n\n/\n1\n8/;t loop
    s/\n1\n/\n\n1/;t loop
    s/\(.\)\n\n/\n\n\1/;t loop
    s/^\n\n//
    

    Dividing an even number by 2, is the same logic, but from left to right instead of right to left:

    s/^/\n\n/
    :loop
    s/\n1\n0/5\n\n/;t loop
    s/\n\n0/0\n\n/;t loop
    s/\n1\n1/5\n1\n/;t loop
    s/\n\n1/\n1\n/;t loop
    s/\n1\n2/6\n\n/;t loop
    s/\n\n2/1\n\n/;t loop
    s/\n1\n3/6\n1\n/;t loop
    s/\n\n3/2\n1\n/;t loop
    s/\n1\n4/7\n\n/;t loop
    s/\n\n4/2\n\n/;t loop
    s/\n1\n5/7\n1\n/;t loop
    s/\n\n5/2\n1\n/;t loop
    s/\n1\n6/8\n\n/;t loop
    s/\n\n6/3\n\n/;t loop
    s/\n1\n7/8\n\n/;t loop
    s/\n\n7/3\n1\n/;t loop
    s/\n1\n8/9\n\n/;t loop
    s/\n\n8/4\n\n/;t loop
    s/\n1\n9/9\n1\n/;t loop
    s/\n\n9/4\n1\n/;t loop
    s/\n1\n/5\n\n/;t loop
    s/\n\n\(.\)/\1\n\n/;t loop
    s/\n\n$//
    

    Combining those, this script do the job:

    h
    s/, start.*//
    s/^/\n\n/
    t loopa
    :loopa
    s/\n1\n0/5\n\n/;t loopa
    s/\n\n0/0\n\n/;t loopa
    s/\n1\n1/5\n1\n/;t loopa
    s/\n\n1/\n1\n/;t loopa
    s/\n1\n2/6\n\n/;t loopa
    s/\n\n2/1\n\n/;t loopa
    s/\n1\n3/6\n1\n/;t loopa
    s/\n\n3/2\n1\n/;t loopa
    s/\n1\n4/7\n\n/;t loopa
    s/\n\n4/2\n\n/;t loopa
    s/\n1\n5/7\n1\n/;t loopa
    s/\n\n5/2\n1\n/;t loopa
    s/\n1\n6/8\n\n/;t loopa
    s/\n\n6/3\n\n/;t loopa
    s/\n1\n7/8\n\n/;t loopa
    s/\n\n7/3\n1\n/;t loopa
    s/\n1\n8/9\n\n/;t loopa
    s/\n\n8/4\n\n/;t loopa
    s/\n1\n9/9\n1\n/;t loopa
    s/\n\n9/4\n1\n/;t loopa
    s/\n1\n/5\n\n/;t loopa
    s/\n\n\(.\)/\1\n\n/;t loopa
    s/\n\n$//
    H
    g
    s/.*, start/, start/
    s/\n.*//
    s/$/\n\n/
    t loopb
    :loopb
    s/0\n1\n/\n\n1/;t loopb
    s/0\n\n/\n\n0/;t loopb
    s/1\n1\n/\n\n3/;t loopb
    s/1\n\n/\n\n2/;t loopb
    s/2\n1\n/\n\n5/;t loopb
    s/2\n\n/\n\n4/;t loopb
    s/3\n1\n/\n\n7/;t loopb
    s/3\n\n/\n\n6/;t loopb
    s/4\n1\n/\n\n9/;t loopb
    s/4\n\n/\n\n8/;t loopb
    s/5\n1\n/\n1\n1/;t loopb
    s/5\n\n/\n1\n0/;t loopb
    s/6\n1\n/\n1\n3/;t loopb
    s/6\n\n/\n1\n2/;t loopb
    s/7\n1\n/\n1\n5/;t loopb
    s/7\n\n/\n1\n4/;t loopb
    s/8\n1\n/\n1\n7/;t loopb
    s/8\n\n/\n1\n6/;t loopb
    s/9\n1\n/\n1\n9/;t loopb
    s/9\n\n/\n1\n8/;t loopb
    s/\n1\n/\n\n1/;t loopb
    s/\(.\)\n\n/\n\n\1/;t loopb
    s/^\n\n//
    H
    g
    s/[^\n]*\n//
    s/\n//
    

    (Much easier in awk thought.)

    Note: I once saw a Turing Machine implementation is sed, so I try to remember that anything that can be done with a programming language can be done in sed. That of course does not mean that sed is the good tool in all situations.

提交回复
热议问题