如何用sed减少(减去)文件中的数字

时间:2014-09-12 16:12:45

标签: bash unix sed

我有一些源代码,如下所示,我在C中调用了一个函数:

void myFunction (
    &((int) table[1, 0]),
    &((int) table[2, 0]),
    &((int) table[3, 0])
);

...唯一的问题是该函数有> 300个参数(它是一个自动生成的包装器,用于初始化和调用整个模块;它是给我的,我无法更改它)。正如您所看到的:我开始使用1而不是0来访问数组...很棒的时候,修改所有300个参数,即将数组的x坐标减去300 x,用手。

我正在寻找的解决方案是我如何强迫sed为我做的工作;)

编辑:请注意,上面用于访问C中的二维数组的语法无论如何都是错误的!当然它应该是[1][0] ...(所以不要只是复制和粘贴;))

2 个答案:

答案 0 :(得分:1)

基本上,我提出的命令如下:

sed -r 's/(.*)(table\[)([0-9]+)(,)(.*)/echo "\1\2$((\3-1))\4\5"/ge' inputfile.c > outputfile.c

嗯,第一眼看上去并不是很直观 - 我几乎找不到每一个例子的错误解释。

所以我会尝试对此作出详细解释:

sed

- >基本命令

-r

- >您找到的大多数示例都使用-e;但是,-r参数(仅适用于GNU sed)启用扩展正则表达式,并为正则表达式中的+提供支持。它基本上意味着"一个或多个匹配"。

's/input/output/ge'

- >这是基本的替换语法。它基本上意味着"替换'输入'通过'输出'"。 /g是"全球" flag,即sed将替换所有出现而不仅仅是第一个出现。您可以添加额外的e以在bash中执行结果。这是我们在这里要做的事情来处理计算。

(.*)

- >这匹配" everthing"从上一场比赛到下一场比赛

(table\[)

- > \是为了逃避括号。表达式的这一部分将匹配像table[

这样的字符串
([0-9]+)

- >这个数字与至少有一位数的数字匹配,但是,它也可以匹配更高的数字,只有一个数字。

(,)

- >这只是匹配逗号,

(.*)

- >并再次:行的其余部分

现在有趣的部分:

echo "\1\2$((\3-1))\4\5"
  • echo是一个bash命令
  • \n(您可以使用\1\9的每个值)是某种"变量"对于输入:\1将包含第一个匹配,\2秒匹配,... - >这有助于您保留输入字符串的一部分
  • $((1+1))是一个简单的bash语法,用于计算双括号内的术语值(在上面的完整sed命令中,\3当然会自动替换为第三场比赛,即括号内的第一部分,以访问桌子的单元格)
  • 请注意,我们在回显内容周围使用引号,以便能够处理包含&等字符的行,否则这些字符将不起作用

最后提到的e \ge将触发bash中结果的执行。例如。问题中示例源代码的前两行将生成以下bash语句:

echo "void myFunction ("
echo "    &((int) table[$((1-1)), 0]),"

正在执行并产生以下输出:

void myFunction (
    &((int) table[0, 0]),

......这很像我想要的东西:)

顺便说一句:      文字> output.c 是一种简单的bash语法,用于将text(或在本例中为sed - 已处理的源代码)输出到名为output.c的文件。


关于此主题的良好链接是:

啊,还有一件事:你也可以在Windows上的sed中使用git-Bash - 如果你被迫"强迫"在像我这样的工作中使用Windows;)

PS:在此期间,我可以轻松地手动完成此操作,但使用sed更有趣;)

答案 1 :(得分:1)

以下是使用Perl的另一种方式:

perl -pe 's/(table\[)(\d+)(,)/$1.($2-1).$3/e' file.c

这使用e修饰符在替换中执行表达式。捕获组连接在一起,但中间组从其值中减去1。

这将输出到标准输出,以便您可以检查它是否符合您的要求。如果您满意,可以添加-i开关来覆盖原始文件。