Combining shell variables and negation in sed
Specific example here is that I want to insert a string inside a second (last) instance of another string, while ignoring another string, e.g. for the input example below, I want to replace every last instance of group_ or field_ on each line, but skip any that contain _type.
The problem is negation is accomplished with:
sed '/pattern to ignore/!s/pattern to replace/replace with/'
This works fine with single quotes, but need double quotes to use shell variables inside sed. With double quotes, the shell complains about the exclamation mark:
bash: !s/\: event not found
One workaround is to place the negation pattern itself inside a shell variable and pass that:
neg='/pattern to ignore/!'
sed "${neg}s/pattern to replace/replace with/"
Example input:
$ egrep "group|field" test
'group_type' => 'standard',
'group_name' => 'group_name',
'group_name' => 'group_home',
'group_name' => 'group_family_members',
'field_name' => 'field_firstname',
'field_name' => 'field_home_address_1',
Code:
neg='/_type/!'
for n in 1 2 3 4; do
egrep "group|field" test > test.$n
for t in group field; do
sed -i "${neg}s/\(.*\)${t}_/\1${t}_l${n}_/" test.$n
done
done
Result:
$ head test.*
==> test.1 <==
'group_type' => 'standard',
'group_name' => 'group_l1_name',
'group_name' => 'group_l1_home',
'group_name' => 'group_l1_family_members',
'field_name' => 'field_l1_firstname',
'field_name' => 'field_l1_home_address_1',
==> test.2 <==
'group_type' => 'standard',
'group_name' => 'group_l2_name',
'group_name' => 'group_l2_home',
'group_name' => 'group_l2_family_members',
'field_name' => 'field_l2_firstname',
'field_name' => 'field_l2_home_address_1',
==> test.3 <==
'group_type' => 'standard',
'group_name' => 'group_l3_name',
'group_name' => 'group_l3_home',
'group_name' => 'group_l3_family_members',
'field_name' => 'field_l3_firstname',
'field_name' => 'field_l3_home_address_1',
==> test.4 <==
'group_type' => 'standard',
'group_name' => 'group_l4_name',
'group_name' => 'group_l4_home',
'group_name' => 'group_l4_family_members',
'field_name' => 'field_l4_firstname',
'field_name' => 'field_l4_home_address_1',
2 Comments
1. kev replies at 5th February 2012, 5:27 am :
Your first example has a typo:
2. Alain Kelder replies at 5th February 2012, 5:47 pm :
Fixed. Thanks, kev!
Leave a comment