GNU sed version 4.1.4 on Windows XP SP3 from GnuWin32
I think that I've come across a seemingly simple text file change problem on a INI formatted file that I can't do with SED without side effects edge cases biting me. I've tried to think of various ways of doing this elegantly and quickly with SED but it seems to me that I'm going to have to try with AWK or finally learn PERL and move to it.
However, before I take these drastic measures let me present the problem here to the SED gurus.
The problem basically stems from the fact that INI format text files do not have a closing tag for the end of the [section], the start of the next section or end of file is the end of the section. This prevents me from using the AWK address range "/ADDR1/,/ADDR2/" feature for limiting the edits to only the section because of the annoying side effect that is the /ADDR2/ range is "inclusive" as per the SED info - 3.2 Selecting lines with `sed' page.
This /ADDR2/ inclusiveness causes problems since once it hits for the next section start then /ADDR1/ doesn't hit again so code for that address range is skipped entirely for the next section causing the SED script to hop-scotch across the INI file skipping every other match eligible section.
Here is an actual sample INI file to work on as an example of the format in case someone is unfamiliar with it. The idea is to change the values in the [supplies_res_*] sections without touching the [supplies_generic] or [trade_generic_sell] sections.
INI File
[supplies_generic]
ammo_12x70_buck = 3, 1
ammo_12x76_zhekan = 3, 0.5
ammo_9x18_fmj = 2, 1
[supplies_res_3]:supplies_generic
ammo_12x76_zhekan = 3, 1
wpn_ak74 = 1, 0.3
[supplies_res_6]:supplies_res_3
ammo_12x76_dart = 3, 0.5
medkit_army = 5, 1
[trade_generic_sell]
ammo_9x18_fmj = 1.5, 1.5
ammo_9x19_fmj = 1.5, 1.5
ammo_11.43x23_fmj = 1.5, 1.5
ammo_12x70_buck = 1.5, 1.5
ammo_12x76_zhekan = 1.5, 1.5
ammo_5.45x39_fmj = 1.5, 1.5
ammo_5.56x45_ss190 = 1.5, 1.5
grenade_rgd5 = 1.5, 1.5
The code below shows the problem with trying to create the address range using the beginning of the next section as the end range, since the inclusiveness of /ADDR2/ address makes the code skip any changes in that section.
SED Code Example - Broken = Hop-Scotch Section Skipping
# Section Address Range
/^[[:space:]]*\[[[:space:]]*%_section%[[:space:]]*\]/I , /^[[:space:]]*\[/
If I try other /ADDR2/ ranges such as "$" for end of file then all sections that contain the same variable will be changed to the end of the file, not something that I want. I cannot use blank line /^[[:space:]]*$/ for ADDR2 since the sections have blank spaces and lines inside them.
If I try to get really clever and do something like below then it doesn't work either no matter what I try to do or think of.
SED Code Example - Broken = Manual Line Reading Doesn't Work (Late Night Idea)
# INI Section
/^[[:space:]]*\[[[:space:]]*%_section%[[:space:]]*\]/I {
# Read Line
: read;
n;
# Next Section Jump Out
/^[[:space:]]*\[[[:space:]]*%_section%[[:space:]]*\]/I! {
/^[[:space:]]*\[/ b;
};
# Variable Line
/^[[:space:]]*%_variable%[[:space:]]*=/I {
# Value Replace
# Note: Retain same whitespace after replacement except for value.
s/^([[:space:]]*%_variable%[[:space:]]*=[[:space:]]*)(.*)[[:space:]]*$/\1%_value%/I;
};
# Loop
b read;
};