Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Change data values based on string query 1

Status
Not open for further replies.

hill007

Technical User
Mar 9, 2004
60
US
I have a large file with different information, but in a structured fashion. I just
want to change the values of one structured information. A small example will help as what exactly I am talking about:

Example set:


0 0 -99 1
22465
1 2
5 6 7

11 1.000 -1 TOP BOT Layer 1
4 4.3 6 7.2
5 3 9 2
1 2 6 3
11 1.000 -1 funny 1
2 6 7
9 4 3
11 1.000 -1 TOP BOT Layer 2
7 8 9 3
8 2 1 4
12 1 8 9
2 5 7 3
11 1.000 -1 funny 2
4 7 9
3 1 2


I now want to change the values in the TOP BOT Layer 1 structure by, say 9 and that in
TOP BOT Layer 2 structure by 6. I just want to change values of TOP BoT Layer structures.
The final dataset would look like:

0 0 -99 1
22465
1 2
5 6 7

11 1.000 -1 TOP BOT Layer 1
9 9 9 9
9 9 9 9
9 9 9 9
11 1.000 -1 funny 1
2 6 7
9 4 3
11 1.000 -1 TOP BOT Layer 2
6 6 6 6
6 6 6 6
6 6 6 6
6 6 6 6
11 1.000 -1 funny 2
4 7 9
3 1 2

Thanks always for any help.

 
Hi

Maybe something like this ? Anyway, you did not say anything about delimiters, so I supposed that the word funny will mark the end of a section.

Code:
awk '
BEGIN { sec=0; split("9 6",vals," ") }
/funny/ { sec=0 }
sec { for (i=1;i<=NF;i++) $i=vals[sec] }
{ print }
$4 $5 $6=="TOPBOTLayer" { sec=$7 }
' inputfile

Feherke.
 
Hi feherke,

The code do not work on the large data set. I am attaching a small part of the dataset. If you make a search "Hydraulic Conductivity Layer 1", the data sets below that layer needs to be changed untill it reaches "Bottom Layer 1".
I have total of 20 such sets in one large file, i.e, to layer 20.

In this test case you can try to change data set below "Hydraulic Conductivity Layer 1" to all values of 14500.2 untill it reaches "Bottom layer 1"

Thanks.
0 0 -9999.000 1 1.000 1 0 0 0 0
4343434343404040404040404040404040
0 1.000(10E12.4) 0 ANISOTROPY
11 1.000(10E12.4) 0 DELTA-X or C
5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02
5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02
5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02
5.0000e+02 5.0000e+02 5.0000e+02 5.0000e+02 1.0200e+04 5.1001e+03 2.5501e+03 2.5501e+03
0 500.000(10E12.4) 0 DELTA-Y or R
11 1.000(10e12.4) -1 PRIMARY STORAGE Layer 1
1.0000e+01 9.9900e+00 1.0000e+01 9.9900e+00 1.0000e+01 9.9900e+00 1.0000e+01 1.0000e+01 9.9900e+00 1.0000e+01
1.0000e+01 9.9900e+00 1.0000e+01 1.0000e+01 1.0000e+01 1.0000e+01 1.0000e+01 1.0000e+01 1.0000e+01 1.0000e+01
9.9900e+00 1.0000e+01 9.9900e+00 9.9900e+00 1.0000e+01 1.0005e+01 1.0000e+01 1.0000e+01
11 1.000(10e12.4) -1 HYDRAULIC CONDUCTIVITY Layer 1
2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06
6.5400e+00 6.5000e+00 6.4900e+00 6.7200e+00 -2.1270e+01 -8.2350e+01 -4.6585e+01 -4.7200e+01
11 1.000(10e12.4) -1 BOTTOM Layer 1
2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06 2.5000e+06
6.5400e+00 6.5000e+00 6.4900e+00 6.7200e+00 -2.1270e+01 -8.2350e+01 -4.6585e+01 -4.7200e+01

 
Hi

I'm sorry, but I don't see the problem. Changing the delimiters and the new value, works with this data too.

Code:
awk '
BEGIN { sec=0; split("14500.2",vals," ") }
/BOTTOM/ { sec=0 }
sec { for (i=1;i<=NF;i++) $i=vals[sec] }
{ print }
$4 $5 $6=="HYDRAULICCONDUCTIVITYLayer" { sec=$7 }
' inputfile

I use GNU [tt]awk[/tt] version 3.1.1 for Linux.

Could you paste some output, pointing what is wrong ? Or upload the a data file somewhere, if the Tek-Tips line wraps mess it up ?

Feherke.
 
Hi Feherke,

I am trying using awk95. I will try again and let you know.
Thanks.
 
Hi Feherke,

It works excellent! I already tested in my 1 GB dataset.
However, I have some formatting issue question.

Is it possible for you to manupulate the code little bit so that the data is in fortran format as in the data set, i.e. it should look like this:

11 1.000(10e12.4) -1 HYDRAULIC CONDUCTIVITY Layer 1
1.4500e+04 1.4500e+04 1.4500e+04 1.4500e+04

I am giving you a star. I will give you another star.
Thanks.
 
Hi

Now I downloaded [tt]awk95[/tt]. Nice piece, works good.

Is it possible for you to manupulate the code (...) should look like this: (...) 1.4500e+04

Maybe some comments in the code would be usefull. [tt]:([/tt]. In fact the new values are strings, so you can write there anything. The new values are enumerated in the [tt]BEGIN[/tt] part as the [tt]split()[/tt] function's first parameter. So in case you want to insert this values in the first 4 section :

[ul]
[li] section HYDRAULIC CONDUCTIVITY Layer 1 = 1.4500e+04[/li]
[li] section HYDRAULIC CONDUCTIVITY Layer 2 = 2005[/li]
[li] section HYDRAULIC CONDUCTIVITY Layer 3 = hello[/li]
[li] section HYDRAULIC CONDUCTIVITY Layer 4 = 3.14[/li]
[/ul]

you have to modify the [tt]split()[/tt]'s first parameter as :

Code:
BEGIN { sec=0; split("1.4500e+04 2005 hello 3.14",vals," ") }
# (...)

Evidently, you can enumerate all the 20 section's new values, separated with space ( or whatever is the [tt]split()[/tt]'s third parameter ).

Feherke.
 
I did, however, there is only one space between them , not two spaces.
What I mean is: 1.4500e+04 1.4500e+04 1.4500e+04

It should be: 1.4500e+04 1.4500e+04 1.4500e+04

There should be two spaces between them.
 
Hi

I did, however, there is only one space between them , not two spaces.

When [tt]awk[/tt] prints out the record, puts the value of the [tt]OFS[/tt] variable between the fields. So you have to set this to two spaces :

Code:
BEGIN { [COLOR=red]OFS="  ";[/color] sec=0; split("1.4500e+04 2005 hello 3.14",vals," ") }
# (...)

Or, as I wrote, the string containing the new values is splited on spaces. So, if you change the separator character to something else, lets say a "[tt]|[/tt]" ( pipe ), then you can use space as part of the new value :

Code:
BEGIN { sec=0; split("1.4500e+04 [COLOR=red]|[/color]2005 [COLOR=red]|[/color]hello [COLOR=red]|[/color]3.14 ",vals,"[COLOR=red]|[/color]") }
# (...)

Feherke.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top