Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to merge the matching pattern with awk on a Solaris system.

$ luxadm probe 
 No Network Array enclosures found in /dev/es

 Found Fibre Channel device(s): 
 Node WWN:2000000c50f1c8da Device Type:Disk device 
 Logical Path:/dev/rdsk/c1t1d0s2 
 Node WWN:2000000c50f1d9c9 Device Type:Disk device 
 Logical Path:/dev/rdsk/c1t0d0s2

Note - While I am trying with awk, it takes Only one line merging from last.

$ luxadm probe |awk '/Node/{n=$2}/Logical/{l=$2} END {print n,l}' 
 WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2

While the output expected is:

WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2
WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2 
share|improve this question

4 Answers 4

up vote 2 down vote accepted

The short answer which isn't mentioned yet in awk

awk '/Node/{n=$2; getline; print n " "$2; next}' filename
  • /Node/ # Look for pattern Node and store the second field in n variable n=$2
  • getline # Move to the next line (This is where Logical line starts), print what's stored in n variable and then second field of the next line.
  • next # Stop processing current record and move to the next one.
share|improve this answer
1  
Your codes works.. can you explain please , I wana learn.. $ luxadm probe | awk '/Node/{n=$2; getline; print n " "$2; next}' WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2 WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2 –  Karn yesterday
    
@Costas - Your last two codes working perfectly .. Could you pleas explain ... $ luxadm probe | awk '/Node/{printf "%s ", $2}/Logical Path/{print $2}' WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2 WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2 $ luxadm probe | awk '/Node/{wwn=$2}/Logical Path/{print wwn,$2}' WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2 WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2 –  Karn yesterday
    
@Karn Well many answers here are correct. I think you just need to get your head around and see if you understand it. All answers are explained to a great extent imo. –  val0x00ff yesterday

The reason it's faililng is because you are only printing the variables you capture once, in an END{} block. This means that only the last two will be printed. @Costas already gave you a more elegant approach, but you could also use the same logic you were trying with a small change:

awk '{ if(/Node/){
        if(length(n)){print n,l} ## if we have an n, print them
        n=$2
        }
        if(/Logical/){l=$2}
      } 
        END {print n,l}' 

Alternatively, you could use other tools:

  1. GNU grep/perl

    luxadm probe |  grep -Po '^\s*(Node|Logical)\s*\K.*?(\s|$)' file | 
        perl -lne '$. % 2 ? printf : print'
    
  2. Perl

    luxadm probe |  
      perl -ne 'chomp;if(s/.*(WWN:.*?)\s.*/$1 / || s/.*(Path:.*?)$/$1\n/){print}'
    
share|improve this answer
    
Still its not giving the desired as it getting only 4th field.. I am a learner so trying to fight with this puzzle with your expertise guys.. $ luxadm probe | awk -F":| " '/Node/{printf "%s ", $3":"$4}/Logical Path/{print $4}' Disk device: Disk device: –  Karn yesterday
    
@Karn did you try the one (ones, now, see update) in my answer? The one you gave in the comment above will fail, yes, but is not the one I posted. –  terdon yesterday
    
@Karn (please answer comments in the place they were asked, I don't get pinged otherwise). I know you showed us the output of luxadm but your comment to Costas's answer mentioned "you have mail in /var/mail/root". Is that in the input? If you try these and they fail, please edit your question and include the specific error messages/output you get. That way, we can correct it. –  terdon yesterday
    
@terdon a great perl one! –  val0x00ff yesterday
    
@terdon - my apologies, going out of the bay while answering , may be because I am a first time user on the site..Moreover I tried your code which is throwing errors .. please see below.. $ perl -ne 'chomp;if(s/.*(WWN:.*?)\s.*/$1 / || s/.*(Path:.*?)$/$1\n/){print}' ^C$ [2] + Done(2) luxadm probe | grep -Po '^\s*(Node|Logical)\s*\K.*?(\s|$)' file | perl -lne '$. % 2 ? printf : print' $ –  Karn yesterday

You should use sed, in my opinion. In the first place, it will usually outperform awk, and, in this case, it offers a more simple solution overall:

sed -n 'N;s/Node \([^ ]*\).*Logical/\1/p' <infile

...which, given your example data, prints...

 WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2
 WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2

For each line read, sed also gets the Next appended to pattern space following an inserted \newline delimiter. So the above s///ubstitution spans two lines, and prints the two fields you want separated only by a space and only when a match is found.

The above sed syntax should be fully portable to any POSIX system.

share|improve this answer

If you want awk

awk -v RS=' Node ' -v FS=' Logical Path:| ' '/WWN/{print $1,$6}'

Other (may be simple)

awk -F":| " '/Node/{printf "%s ", $3":"$4}/Logical Path/{print $4}'

with remain Path:

awk '/Node/{printf "%s ", $2}/Logical Path/{print $2}'

or

awk '/Node/{wwn=$2}/Logical Path/{print wwn,$2}'

And GNU sed at last:

sed -n '/WWN/{s/^\s*\S* *\|\( \S*\)\{3\}\s*$//g;N;s/\n\s*\S*//;p}'
share|improve this answer
    
its does not work for the situation... $ luxadm probe | awk -v RS=' Node ' -v FS=' Logical Path:| ' '/WWN/{print $1,$6}' awk: syntax error near line 1 awk: bailing out near line 1 you have mail in /var/mail/root –  Karn yesterday
    
@Karn in that case, please edit your question and include the entire output of luxadm probe. –  terdon yesterday

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.