所以我正在测量c程序经过的总时间。通过这样做,我一直在运行这个shell脚本,它使用sed来替换我的c程序中某行中间某处定义的常量(低于:N)的值。
#define N 10 // This constant will be incremented by shell program
在你告诉我我应该使用变量并对使用它的函数进行计时之前,我必须在一次运行时从外部计算整个程序的执行时间(意味着没有重新分配N)。
我一直在shell脚本中使用以下内容来帮助:
tmp=$(sed "11s/[0-9][0-9]*/$INCREMENTINGVAR/" myprogram.c); printf "%s" "$tmp" > myprogram.c
用我的INCREMENTINGVAR(替换)替换3位数字。但是,当替换为2位数时,这对我来说似乎不适用。 Sed仅替换前两个字符,并保留上一次运行的前三个数字而不删除它。
TESTS=0
while [ $TESTS -lt 3 ]
do
echo "This is test: $TESTS"
INCREMENTINGVAR=10
while [ "$INCREMENTINGVAR" -lt 10 ]
do
tmp=$(sed "11s/[0-9][0-9]*/$INCREMENTINGVAR/" myprogram.c); printf "%s" "$tmp" > myprogram.c
rm -f myprog.c.bak
echo "$INCREMENTINGVAR"
gcc myprogram.c -o myprogram.out; ./myprogram.out
INCREMENTINGVAR=$((INCREMENTINGVAR+5))
done
TESTS=$((TESTS+1))
done
我应该做些什么吗?
编辑:添加整个shell脚本;改变了sed的模式。
答案 0 :(得分:1)
您是否只想用新值替换第11行的任何数字字符串?如果是这样,你就写了:
sed -e "11s/[0-9][0-9]*/$INCREMENTINGVAR/"
查找一个或多个数字的序列,并用$INCREMENTINGVAR
中的当前值替换它。这将从9翻转到10,从99到100,从999到1000,等等。事实上,没有什么可以阻止你从1跳到987,654,如果这是你想要做的。
使用sed
的GNU和BSD(Mac OS X)版本,您可以自动覆盖该文件。可移植的方式(意思是,与sed
的GNU和BSD变体一样工作)是:
sed -i.bak -e "11s/[0-9][0-9]*/$INCREMENTINGVAR/" myprog.c
rm -f myprog.c.bak
这会创建一个备份文件(并将其删除)。问题是GNU sed仅需要-i
而BSD sed
需要-i ''
(两个参数)才能在没有备份的情况下进行原位更改。您可以确定可移植性不相关。
请注意,使用行号来识别必须更改的内容是微妙的;微不足道的变化(新标题,更多评论)可能会改变行号。使用上下文搜索可能会更好:
sed -i.bak -e "/^#define N [0-9]/ s/[0-9][0-9]*/$INCREMENTINGVAR/" myprog.c
rm -f myprog.c.bak
这假设define
和N
之间的空格和数字。如果你可能有空格或标签,那么你可以写:
sed -i.bak -e "/^[[:space:]]*#[[:space:]]*define[[:space:]]\{1,\}N[[:space:]]*\{1,\}[0-9]/ s/[0-9][0-9]*/$INCREMENTINGVAR/" myprog.c
rm -f myprog.c.bak
查找#
之前的可选前导空格,#
和define
之间的可选空格,define
之间的强制空格(至少一个,可能很多) 1}}和N
,以及N
和数字的第一个数字之间的强制空格。但是,您的输入可能不是那么草率,而且更简单的搜索模式(如第一个选项)足以满足您的需求。您还可以编写代码来将偏心格式化的#define
行标准化为规范表示 - 但同样,您很可能不需要。
如果您在同一文件中的其他位置包含以下内容:
#undef N
#define N 100000
你也不得不担心匹配这一行的模式。但是,很少有文件这样做;它在实践中可能不是一个问题(如果是这样的话,代码通常可能比这里可以处理的问题更多)。一种可能性是将范围限制为前30行,假设第一个#define N 123
在某个范围内而第二个不在。
sed -i.bak -e "1,30 { /^[[:space:]]*#[[:space:]]*define[[:space:]]\{1,\}N[[:space:]]*\{1,\}[0-9]/ s/[0-9][0-9]*/$INCREMENTINGVAR/; }" myprog.c
rm -f myprog.c.bak
还有其他多种技巧可以用来限制伤害,并有不同程度的冗长。例如:
sed -i.bak -e "1,/^[[:space:]]*#[[:space:]]*define[[:space:]]\{1,\}N[[:space:]]*\{1,\}[0-9]\{1,\}/ \
s/^[[:space:]]*#[[:space:]]*define[[:space:]]\{1,\}N[[:space:]]*\{1,\}[0-9]\{1,\}/#define N $INCREMENTINGVAR/; }" myprog.c
rm -f myprog.c.bak
使用正则表达式通常是特异性和详细程度之间的判断调用 - 您可以使事情非常安全但难以阅读,或者您可以冒一个小风险,使您的可读代码与无意识的内容相匹配。
答案 1 :(得分:0)
我不完全确定你为什么现在没有按预期工作。 - 它可能与您使用的sed版本有关。你用的是什么版本?您可以查看sed --version
- 我已安装4.2.2。
我似乎无法自己复制这个问题 - 但是你总是可以试试这个,我觉得它有帮助。
11s/[0-9]\{1,3\}/$INCREMENTINGVAR/
如果我记得 - {n,m}
表示"匹配至少N次,最多M次。"在你的情况下,它将匹配2或3位数,然后用增量var的任何内容替换它们 - 它不应该是替换它是什么。