how to fix this awk script?

i have a log file while looks like this

++
user_a blabla
blabla nas_b blabla user_d
this is a user_a
junk line
another junk line
user_c nas_m blabla
++

basically most of the lines contain a "user" keywords, and the rest of the lines do not have "user" at all.

So I have the following script, which just extracts the user part(if that line has a user keyword) from each line

awk '{ for (i=0; i<=NF; i++)
if($i~/user/)
{a=$i}
else
{continue}
{print a}
}' /tmp/test

and when I run it, I got the following result

user_a
user_d
user_a
user_a #<===actually there is no user in that line at all.
user_c

why this happens and how can I fix my script? thanks

I think it is because you are always printing a value. So, you are not over-writing 'a' ni the instance of the 4th line, so when you print the variable, you are getting the last stored value of 'a'.
Perhaps as the first line ater your else, do a

a=""

to blank out the last 'a' value?

I reliazed that problem, but it seems I can not fix the problem, here is the modified script

awk '{ for (i=0; i<=NF; i++)
if($i~/user/)
{a=$i}
else
{a="no"}
{ continue}
{print a}
}' /tmp/test

and the output change to

no
user_d
user_a
no
no

which is not correct at all.

With awk:

awk '{ 
  for (i=1; i<=NF; i++)
    if ($i ~ /user/)
      print $i
      }' infile

With Perl:

perl -lne'print $1 while /(user[^\s]*)/g' infile

With GNU grep:

grep -o 'user[^ \t]*' infile

Thanks, I know in this example I gave, egrep is a better choice, but actually my real work is "finding out both "user" and "nas" part, and then print out the result.

below is the result I want

+
user_a nas_b
user_d nas_b
user_a
user_c nas_m
+

But the problem is, no matter how i modified my script, I just won't get the desired result...

[quote=radoulov;302286540]
With awk:

awk '{ 
  for (i=1; i<=NF; i++)
    if ($i ~ /user/)
      print $i
      }' infile

With Perl:

I don't understand the logic ...
Why user_d nas_b?

sorry, that was a typo

an actual (with blah-s) file sample would be helpful. A desired output (based on a sample input) would not hurt either.
Please use vB Codes when posting samples/quotes.

sure, let me be more clear, here is the file test

$more /tmp/test
user_a blabla nas_b
blabla nas_b blabla user_d
this is a user_a
another junk line
user_c nas_m blabla

please note, user and nas may or may not appear on each line, and the position of user and nas are not fixed, they can appear in any column.

I need a script to scan each line, if any line contains user or nas, or both, they will be extracted from the line and be printed out, and i want print user before nas if a line has both words. in my case, the result will be look like:

user_a nas_b
user_d nas_b
user_a
user_c nas_m

I tried to monky with awk for a while, but just can not figure out a good way to make it.

Any help will be greatly appreciated.

awk  '/user|nas/{ for (i=1; i<=NF; i++) {
                   if ($i ~ /user/) printf $i FS 
                   if ($i ~ /nas/) a=$i } 
                  for (j in a) printf a[j] FS
                  print "" ; split("",a) }' filename

this script works for my example ! I must admit I don't understand this awk array thing, I figure there are tons of awk stuff to learn.

but the thing is, it appears that this script does not always work , for example, when I run the script against the following line, i got error

$more /tmp/test2
08:05:55.255412 rad-access-req 58 [id 57] Attr[ Service_type{Authenticate Only} user{Defcon} Pass nas_ipaddr{1.2.2.3} ] (DF)

and the error message is:

"awk: a is not an array
record number 1"

Given your requirements, the code works fine either with gawk or old awk. Try to modify it to get your desired output.

$ cat file
user_a blabla nas_b
blabla nas_b blabla user_d
this is a user_a
another junk line
08:05:55.255412 rad-access-req 58 [id 57] Attr[ Service_type{Authenticate Only} user{Defcon} Pass nas_ipaddr{1.2.2.3} ] (DF)
another junk line
user_c nas_m blabla

$ awk  '/user|nas/{ for (i=1; i<=NF; i++) {
                   if ($i ~ /user/) printf $i FS 
                   if ($i ~ /nas/) a=$i } 
                  for (j in a) printf a[j] FS
                  print "" ; split("",a) }' file

user_a nas_b
user_d nas_b
user_a
user{Defcon} nas_ipaddr{1.2.2.3}
user_c nas_m

after I install gawk, problem fixed, thanks a lot!

sorry, one more question, I have been trying to read some awk documents, but apparently the time is just not enough for me to pick up the awk "array" very quickly. Right now I just saved the script.

If I insert one more keyword group into the test file, how can i tune this awk script to pick up all 3 keywords and print user first, nas second and group last?

exmple,
$more /tmp/test
user_a blabla nas_b group_a
blabla nas_b group_b blabla user_d
this is a user_a, group_c
another junk line
group_d user_c nas_m blabla

and the desire output

user_a nas_b group_a
user_d nas_b group_b
user_a group_c
user_c nas_m group_d

thank in advance :b::b::b:!

awk  '/user|nas|group/{ for (i=1; i<=NF; i++) {
                   if ($i ~ /user/) printf $i FS 
                   if ($i ~ /nas|group/) a=$i } 
                  for (j in a) printf a[j] FS
                  print "" ; split("",a) }' file

Thanks for answering my question, I greatly appreciated! but the output is not 100% I want, see the last line, nas_m is on the last column. while i want all the nas show up on the second column.

user_a group_a nas_b
user_d nas_b group_b
user_a, group_c
user_c group_d nas_m

ok, I see what he's doing:

awk '/user|nas|group/{ for (i=1; i<=NF; i++) {
                   if ($i ~ /user/) printf $i FS
                   if ($i ~ /nas/) a=$i
                   if ($i ~ /group/) b=$i }
                  for (j in a) printf a[j] FS
                  for (j in b) printf b[j] FS
                  print "" ; split("",a); split("",b) }' file

thank you thank you thank you! :b: :b: :b:

This little script is awesome! Saved for future use.