如何使用sed / perl只查找2d数组并替换文本?

时间:2017-03-13 07:51:12

标签: regex perl sed

目前我有大量代码如下:

static double    testVar1          [2][8]  = {0.0}    ;  /* This is for testing var 1 */
static double    var_test2         [3][2]  = {0.0}    ;  /* This is for testing var 2 */
static double    var_test3         [4]     = {0.0}    ;  /* This is for testing var 3 */

c ++中的2d数组用双花括号初始化,所以我只需要找到2d数组并改变它:

static double    testVar1          [2][8]  = {{0.0}}  ;  /* This is for testing var 1 */
static double    var_test2         [3][2]  = {{0.0}}  ;  /* This is for testing var 2 */
static double    var_test3         [4]     = {0.0}    ;  /* This is for testing var 3 */

我一直在尝试使用sed来使用分组,但我无法弄清楚如何逃避括号,有些帖子建议不要逃避。我也试过没有扩展的正则表达式。

刚才,我发现sed中只有9个分组是可能的,所以现在完全卡住了。有什么建议吗?

sed -i -r 's/(.*)(\[)([0-9]+)(\])(\[)([0-9]+)(\])(.*)(\{)(0.0)(\})(.*)/echo "\1\2\3"/ge'

5 个答案:

答案 0 :(得分:2)

使用带有以下正则表达式的perl脚本:

test <- manova(cbind(y1,y2,y3) ~ x1, data = data, subject = "id")

并将其替换为\w+\s*(?:\[\d+\]){2}\s*=\s*\K\{([\d.]*)\} ,请参阅a demo on regex101.com

<小时/> 细分,这说:

\{\{\1\}\}

答案 1 :(得分:2)

Perl one-liner,对2u1e-06l等文字持谨慎态度

perl -pe's/(?:\[ [^]]+ \]){2} \s*=\s* \K (\{ [^}]+ \})/{$1}/x' in > out

(?:)组(没有捕获)和(?:\[[^]]+\]){2}用于[n][m]\Kpositive lookbehind的形式,也会删除之前的匹配,因此我们不必将它们放回去。

[]内的整数只是数字,{}中的浮点数为n.m,这简化了

perl -pe's/(?:\[\d+\]){2}\s*=\s*\K( \{[\d.]+\} )/{$1}/x' in > out

请注意,[\d.]允许出现各种错误的内容,例如.2..3,但这是一个不同的问题。

但是,请注意使用2u(带后缀)等数字的文字,以及vec[1.2e+01]甚至vec[1.2]。 float / double literals的变化符号也更有可能出现在数据中。总而言之,我会选择像

这样的更圆润的模式
perl -pe's/(?:\[ [\d\w+-.]+ \]){2}\s*=\s*\K(\{ [\d\w+-.]+ \})/{$1}/x' in > out

请注意,这允许使用各种错误格式,因此无法很好地检查数据。

答案 2 :(得分:1)

这是sed尝试解决了正则表达式的皱纹。

sed -i -r 's/(.*\[[0-9]+\]\[[0-9]+\].*)(\{0.0\})(.*)/\1{\2}\3/'

你有大量无动机的额外分组括号,所以\1\2\3只会引用比赛的最开始。我把它们拿出来了。请记住,捕获是从左到右排序的,因此第一个左括号创建组\1,第二个捕获到\2等等。

GNU sed扩展名/e允许您在替换字符串上调用shell,但在这种情况下,这没有添加任何值并引入了大量额外的可能错误,因此将其取出是一个明智的选择。如果你期望每行有多个匹配,/g选项会有意义,但是你的例子没有显示多个匹配的输入行的例子,整个脚本需要相当复杂才能支持它,所以我也把它拿出来了。

根据您尝试处理的语言和文件的规律性,您可能希望在结束和打开方括号之间允许空格,或者不允许;并且结束方括号和开口花括号之间的“任何”通配符看起来有点容易出现误报(匹配你不想要它的地方) - 可能会改变它只允许空格和等号,如{{ 1}}而不是[ =]*

答案 3 :(得分:1)

sed的另一种方法:

sed -i -r 's/((\[[0-9]\]){2} *= )(\{[^}]*\})/\1{\3}/' file

和BRE模式相同:

sed -i 's/\(\(\[[0-9]\]\)\{2\} *= \({[^}]*}\)\)/\1{\2}/' file

答案 4 :(得分:1)

sed -i '/]\[/s/[{}]/&&/g' file