算术涉及的Sed替换可能吗?

时间:2011-08-05 15:33:00

标签: regex sed

我需要修改的文件包含以下内容:

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

我想要该文件,以便阻止尺寸的值除以2,而的值长度将乘以2。

由于我必须对一大堆文件进行此类修改,因此我正在考虑使用 Sed 为我做替换工作。但我不确定在匹配和替换过程中是否允许进行计算。

4 个答案:

答案 0 :(得分:9)

我总是尝试使用sed解决使用标记的每个问题。但是在这里完成你要用awk做的事情是如此容易。 (在这种情况下使用sed太难了。)所以,这是我使用awk的解决方案:

$ echo "block: 16, size: 16, start: 8, length: 4" | awk '{
    printf "%s %d, %s %d, %s %d, %s %d\n", $1, $2/2, $3, $4/2, $5, $6*2, $7, $8*2
}'
block: 8, size: 8, start: 16, length: 8

答案 1 :(得分:6)

(执行此操作的正确工具是awk,但是为​​了获得sed练习的乐趣......)

有可能在sed。毕竟,根据一些简单的规则,乘以2是最后一位数的替换:

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

为了处理进位数,每个规则应写两次。

这个可以用sed -f script运行的sed脚本在输入行上的所有数字中乘以2:

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//

将偶数除以2是相同的逻辑,但是从左到右而不是从右到左:

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$//

结合这些,这个脚本完成工作:

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//

(在awk思想中容易多了。)

注意:我曾经看过图灵机的实现是sed,所以我试着记住任何可以用编程语言完成的事情都可以在sed中完成。当然,这并不意味着sed在所有情况下都是很好的工具。

答案 2 :(得分:5)

Perl在这里很有用:

perl -pe '
  s{(\D+)(\d+)(\D+)(\d+)(\D+)(\d+)(\D+)(\d+)}
   {$1 . $2/2 . $3 . $4/2 . $5 . $6*2 . $7 . $8*2}e
' file

如果您想就地修改文件,perl会有一个像{sed这样的-i选项。

答案 3 :(得分:0)

不要认为这是可能的。参见例如http://www.delorie.com/gnu/docs/sed/sed_15.html

但是,如果您只有一小组可能的块,大小,开始和长度值,那么对所需的替换进行硬编码可能是最快的。下一个最简单的选项可能是使用awk,但无法就地修改文件。