LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   awk multilines / grep colums.. or indeed anything that will work (https://www.linuxquestions.org/questions/programming-9/awk-multilines-grep-colums-or-indeed-anything-that-will-work-688605/)

baidym 12-05-2008 03:09 PM

awk multilines / grep colums.. or indeed anything that will work
 
Hi everybody,

I simply can not get this to work can anyone help? I't does'nt matter how it's done if it works :)

I am trying to pull out rows with flags of 8 and 12 (in column 6) but also the lines above and below

I've tried %grep -E -C1 '[[:space:]]([8]|12)[[:space:]]' <file>

BUT,
I also need to relabel the flags so 0=1 and 8 or 12 = 3

file# point# usr pc label flag
1 1 174 1 1312001 0
2 1 175 1 1312001 0
3 1 176 1 1312001 8
4 1 177 1 1312001 0
5 1 178 1 1312001 0
6 1 179 1 1312001 0
7 1 180 1 1312001 0
8 1 181 1 1312001 0
9 1 182 1 1312001 12
10 1 183 1 1312001 0
11 1 184 1 1312001 0

so I would get
2 1 175 1 1312001 1
3 1 176 1 1312001 3
4 1 177 1 1312001 1
8 1 181 1 1312001 1
9 1 182 1 1312001 3
10 1 183 1 1312001 1
11 1 184 1 1312001 1

Can someone PLEASE help me, I'm useless with this.

Thanks M.x.

thecarpy 12-05-2008 04:34 PM

This has to be done in awk, and you need to do something like:

{
if ($6 ~ /12/)
{
$6 = 3;
lastWasTrue = "true";
print previous;
print $0;
}
else if ($6 ~ /8/)
{
$6 = 3;
lastWasTrue = "true";
print previous;
print $0;
}
else if (lastWasTrue == "true")
{
if ($6 ~ /0/)
{
$6=1;
}
print $0;
lastWasTrue = "false";
}
else
{

if ($6 ~ /0/)
{
$6=1;
}
previous=$0;
}
}

wap the code into a file and run awk as:

awk -F\ -f myscript.awk <file>

I have not tested this and I may have forgotten stuff/gotten stuff wrong ... but it should sort of work. Please test, code provided for your convenience, no warranties.

I write in many languages, from java to c, long time no awk ...

radoulov 12-06-2008 07:24 AM

Assuming line 11 in the example output is a typo and your sed supports the -r option:

Code:

sed -rn '
/ (8|(1(|2)))$/!{
  s/ 0$/ 1/;x;d;
  }
/ (8|(1(|2)))$/ {
  s/ [^ ]*$/ 3/
  x;p;x;p
  n;s/ 0$/ 1/;p;x;
}' infile

Or,
a pipeline with GNU grep and AWK:

Code:

grep -EC1 ' (8|(1(|2)))$' infile |
  awk '!/^--/&&$NF=/ 0$/?1:3'

If in the context lines $NF is not always 0:

Code:

grep -EC1 ' (8|(1(|2)))$' infile |
  awk '/ (8|(1(|2))|0)$/{$NF=/ 0$/?1:3}!/^--/'


baidym 12-08-2008 11:54 AM

Works, but has a bug
 
That sed works a treat, but I've discovered a bug that hinders me a bit

When there are two consecutive rows of 8s

IN:
233 1 405 1 1312001 0
234 1 406 1 1312001 8
235 1 407 1 1312001 8
236 1 408 1 1312001 0

OUT:
233 1 405 1 1312001 1
234 1 406 1 1312001 3
235 1 407 1 1312001 8
238 1 410 1 1312001 1

using:

#! /bin/bash -f

sed -rn '
/ (8|(1(|2)))$/!{
s/ 0$/ 1/;x;d;
}
/ (8|(1(|2)))$/{
s/ [^ ]*$/ 3/
x;p;x;p
n;s/ 0$/ 1/;p;x;
}' infile.txt > outfile.txt


Anyone got any ideas to get around this?

Or, If I grep for 8 in column 6 how can I insert a newline so that these lines are easy to spot?

radoulov 12-08-2008 12:18 PM

Something like this:

Code:

sed -rn '
/ (8|(1(|2)))$/!{
s/ 0$/ 1/;x;d;
}
/ (8|(1(|2)))$/{
s/ [^ ]*$/ 3/
x;p;x;p
n
s/ 0$/ 1/
s/ (8|(1(|2)))$/ 3/
p;x;
}' infile

And what should be the expected output, given the above example input?

baidym 12-08-2008 03:45 PM

Clients!!!!!
 
you're a sed guru!!

I'm sorry, but they keep on changing the specs, I'll explain..this is to be a contents file to be read in, the 0's (replaced with 1's) in column 6 are good files, the 8's (replaced with 3's) are bad files.

Now the client is saying they want the start and end of the good files defined as 2 (start), 3 (end) and 1 (bad file). SO if...

IN:
233 1 405 1 1312001 0 #first good file
234 1 406 1 1312001 0
235 1 407 1 1312001 0 #last good file
236 1 408 1 1312001 8 #bad
237 1 409 1 1312001 0
238 1 410 1 1312001 0
239 1 411 1 1312001 8

OUT:
2 233 1 405 1 1312001 1 #start of good records
3 335 1 407 1 1312001 1 #end of good records
1 236 1 408 1 1312001 3 #single file (bad)
2 237 1 409 1 1312001 1 #start of good records
3 238 1 410 1 1312001 1 #end of good records
1 239 1 411 1 1312001 3 #single file (bad)
etc...

Buggers!!

This is geetting quite silly!!

M.x

radoulov 12-09-2008 04:09 AM

Assuming only 0/8 at the end of the line.
Use nawk or /usr/xpg4/bin/awk on Solaris.

Code:

awk '/ 8$/ {
  sub(/ [^ ]*$/, " 3")
  print (!b++ && s) ? s RS $0 : $0
  s = g = 0
  }
/ 0$/ {
  sub(/ 0$/, " 1")
  if (!g++) print
  s = $0; b = 0
  }' infile



All times are GMT -5. The time now is 09:45 AM.