2

I would like to replace the same pattern multiple times (/g). The pattern can appear in a single line or span several lines (2+).

So, for instance, I'd like to change

EXPECT_EQ(50, var1);
EXPECT_EQ(10, 
var2);
EXPECT_EQ(20,
an_expression
_that_takes
_multiple_lines);

to something like

EXPECT_EQ(var1, 50);
EXPECT_EQ(var2, 
0);

EXPECT_EQ(an_expression
_that_takes
_multiple_lines,
20);

The issue is that

sed -E 's/EXPECT_EQ\(([0-9]+), (.*)\);/EXPECT_EQ(\2, \1);/g' file.txt

will only update the first line in the example since the second match I want has 2 lines.

Is there a way to substitute all match independent of how many lines they have? Something like https://regex101.com/r/QmHCyo/1 but with sed.

Whitespaces or new lines in the result string are of no concern. They can have any format since they are automatically fixed later.

1
  • Since this looks like C++, can't you just define a preprocessing macro: #define EXPECT_EQ(a,b) EXPECT_EQ((b),(a)), or via c++ -D 'EXPECT_EQ(a,b)=EXPECT_EQ((b),(a))' -E file.hpp
    – Kusalananda
    Aug 4, 2021 at 6:05

2 Answers 2

2

Using GNU sed stream editor utility with the extended regexes activated -E we can perform the manipulation as shown:

sed -Ee '
  /^EXPECT_EQ\(.*\);$/!{
    $!N;H;z;x;D
  }
  s/\(([^,]+)(,\s*)(.*)\);$/(\3\2\1);/
' file

Result:-

EXPECT_EQ(var1, 50);
EXPECT_EQ(var2, 
10);
EXPECT_EQ(an_expression
_that_takes
_multiple_lines,
20);

Note that we are assuming that the brackets are not nested and the particular function Expect_eq is being modified.

The goal is to accumulate In the pattern space until the brackets balance. After which we flip the two arguments separated by comma and optional space.

0

With GNU sed for -E and -z:

$ sed -Ez 's/(\(\s*)([^),]+\S)(\s*,\s*)([^),]+\S)(\s*\))/\1\4\3\2\5/g' file
EXPECT_EQ(var1, 50);
EXPECT_EQ(var2,
10);
EXPECT_EQ(an_expression
_that_takes
_multiple_lines,
20);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .