user2690569
user2690569

Reputation: 53

Using sed with an array to search for a string plus whitespace

I'm using sed to replace many lines in several files and I've run into a problem. I use an array to give sed many commands but need to include a couple spaces in the search to prevent sed form finding and deleting too many lines. code:

( IFS='|'; sed -rie "/  ${points_r[*]};/d" io_points.dat4; )

The two spaces and ";" are to help avoid deleting lines I don't need to delete. Those lines were deleted, so I tried this as well:

( IFS='|'; sed -rie "/\s\{2,\}${points_r[*]};/d" io_points.dat4; )

My bash version is 3.2.25 and sed version is 4.1.5. How can I search for matches using this array, but include spaces (and ';') in the search? Any help would be greatly appreciated!

EDIT: sample input

  2;  14; 1;I;   0;  1;  0;  66
  3;  14; 1;I;   0;  1;  0;  141
  4;  14; 1;I;   0;  1;  0;  23
  5;  14; 1;I;   0;  1;  0;  26
  7;  14; 1;I;   0;  1;  0;   0

points_r contains the numbers 3 4 and 5, I need to delete the lines which contain 3; 4; and 5; (first column) but not 2; or 7; (they contain a 4 in the second column)

Output would be:

2;  14; 1;I;   0;  1;  0;  66
7;  14; 1;I;   0;  1;  0;   0

Upvotes: 2

Views: 1701

Answers (3)

Dru
Dru

Reputation: 1428

Great script!

The problem is with using the pipe, and also with the array variable.

The 3.2 shell expands these a little differently.

assign the array to a different variable so that you don't have to do array expansion in the sed command (maybe not necessary, but makes things easier):

arr=$points_r[*]

Now do a shell substitution on the 'arr' variable to get the pipes in:

arr2="${arr// /|}"

Then use what you have, it's cool.

My shell prompt is ">>> ", and I unset IFS and OFS before this worked; for some reason they were pipes....

>>> x="${points_r[*]}"
>>> echo $x
3 4 5
>>> y="${x// /|}"
>>> echo $y
3|4|5

run the sed command with $y.

(The IFS won't be passed along to sed, I think. It receives 3 4 5 )

For the sed line you used, you need to enclose the regexp in () so it is one match group, (3 or 4 or 5)

sed -re "/  (${y});/d" io_points.dat4;
  2;  14; 1;I;   0;  1;  0;  66
  7;  14; 1;I;   0;  1;  0;   0

I haven't used the 'i' switch...

Upvotes: 1

user000001
user000001

Reputation: 33337

If you want the values to be in an array, try this script

$ echo "${points_r[@]}"
2 3 4

$ awk -F'[ ;]+' -v p="${points_r[*]}" 'BEGIN{split(p,a," ");for (i in a) b[a[i]]=1}!($2 in b)' file
  2;  14; 1;I;   0;  1;  0;  66
  7;  14; 1;I;   0;  1;  0;   0

Note that this will only work with singe word array elements.

Upvotes: 1

Chris Seymour
Chris Seymour

Reputation: 85815

Unless I misunderstood the requirements then simply do:

$ awk '/^[27];/' file
2;  14; 1;I;   0;  1;  0;  66
7;  14; 1;I;   0;  1;  0;   0

Or with sed:

$ sed '/^[27];/!d' file
2;  14; 1;I;   0;  1;  0;  66
7;  14; 1;I;   0;  1;  0;   0

In fact if this is the case you just want grep:

$ grep '^[27];' file
2;  14; 1;I;   0;  1;  0;  66
7;  14; 1;I;   0;  1;  0;   0

Upvotes: 2

Related Questions