Reputation: 53
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
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
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
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