Re: Join multiple lines in a string based on regex. (Updated)
by BrowserUk (Patriarch) on Dec 16, 2014 at 04:26 UTC
|
#! perl -sw
use strict;
while( <DATA> ) {
chomp;
print "$_ ";
unless( $. % 3 ) {
print "\n";
}
}
__DATA__
array A
physicaldrive 2C:1:1 port 2C:box 1:bay 1 SAS 1 TB OK
physicaldrive 2C:1:2 port 2C:box 1:bay 2 SAS 1 TB OK
array B
physicaldrive 2C:1:3 port 2C:box 1:bay 3 SAS 1 TB OK
physicaldrive 2C:1:4 port 2C:box 1:bay 4 SAS 1 TB OK
array C
physicaldrive 3C:1:5 port 3C:box 1:bay 5 SAS 1 TB OK
physicaldrive 3C:1:6 port 3C:box 1:bay 6 SAS 1 TB OK
array D
physicaldrive 3C:1:7 port 3C:box 1:bay 7 SAS 1 TB OK
physicaldrive 3C:1:8 port 3C:box 1:bay 8 SAS 1 TB OK
Ouput: C:\test>junk
array A physicaldrive 2C:1:1 port 2C:box 1:bay 1 SAS 1 TB OK physical
+drive 2C:1:2 port 2C:box 1:bay 2 SAS 1 TB OK
array B physicaldrive 2C:1:3 port 2C:box 1:bay 3 SAS 1 TB OK physical
+drive 2C:1:4 port 2C:box 1:bay 4 SAS 1 TB OK
array C physicaldrive 3C:1:5 port 3C:box 1:bay 5 SAS 1 TB OK physical
+drive 3C:1:6 port 3C:box 1:bay 6 SAS 1 TB OK
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
Thanks for the reply . It seems we are combining every 3 lines in to a single line , If I am not wrong . The O/P could even stretch to more than 3 lines after matching array and until it hits the next array string .
| [reply] |
|
|
| [reply] |
Re: Join multiple lines in a string based on regex.
by NetWallah (Canon) on Dec 16, 2014 at 05:07 UTC
|
Short code, using a (relatively) complex regex with negative look-ahead for the special case "unassigned":
use strict;
use warnings;
local $/="\narray ";
while (<DATA>){
s/\n(?!unassigned)(:?array)?/ /g;
print my $row=(m/^array/?"":"array "). "$_\n";
}
__DATA__
array A
physicaldrive 2C:1:1 port 2C:box 1:bay 1 SAS 1 TB OK
physicaldrive 2C:1:2 port 2C:box 1:bay 2 SAS 1 TB OK
array B
... etc ...
unassigned
physicaldrive 7C:3:7 port 7C:box 3:bay 7 SAS 1 TB OK
...
Output :
array A physicaldrive 2C:1:1 port 2C:box 1:bay 1 SAS 1 TB OK physicald
+rive 2C:1:2 port 2C:box 1:bay 2 SAS 1 TB OK
array B physicaldrive 2C:1:3 port 2C:box 1:bay 3 SAS 1 TB OK physicald
+rive 2C:1:4 port 2C:box 1:bay 4 SAS 1 TB OK
...
array J physicaldrive 6C:3:3 port 6C:box 3:bay 3 SAS 1 TB OK physicald
+rive 6C:3:4 port 6C:box 3:bay 4 SAS 1 TB OK
array K physicaldrive 7C:3:5 port 7C:box 3:bay 5 SAS 1 TB OK physicald
+rive 7C:3:6 port 7C:box 3:bay 6 SAS 1 TB OK
unassigned physicaldrive 7C:3:7 port 7C:box 3:bay 7 SAS 1 TB OK physic
+aldrive 7C:3:8 port 7C:box 3:bay 8 SAS 1 TB OK
Separating the "unassigned" in $row is left as an exercise.
"You're only given one little spark of madness. You mustn't lose it." - Robin Williams
| [reply] [d/l] [select] |
|
|
Hi,
Here is the O/P that I needed. I probably skipped few lines in my code during my first post .
use strict;
use warnings;
use Data::Dumper;
my %unitMap;
my $skipNext;
my $count = 0;
my $cmd = "somecommand";;
open my $fd, "$cmd|" or return \%unitMap;
while (my $row = <$fd>) {
$row =~ /^$/ and next;
$row =~ s/[,|)|(]//g;
chomp $row;
next if $row =~ /^Smart/g;
$row =~ s/^\s+//;
if( $row =~ /^unassigned/ ){
$skipNext = 2;
next;
}
if( $skipNext ){
$skipNext--;
next;
}
print "$ow\n";
Below is my Data exactly .
data
array A
physicaldrive 2C:1:1 port 2C:box 1:bay 1 SAS 1 TB OK
physicaldrive 2C:1:2 port 2C:box 1:bay 2 SAS 1 TB OK
array B
physicaldrive 2C:1:3 port 2C:box 1:bay 3 SAS 1 TB OK
physicaldrive 2C:1:4 port 2C:box 1:bay 4 SAS 1 TB OK
array C
physicaldrive 3C:1:5 port 3C:box 1:bay 5 SAS 1 TB OK
physicaldrive 3C:1:6 port 3C:box 1:bay 6 SAS 1 TB OK
array D
physicaldrive 3C:1:7 port 3C:box 1:bay 7 SAS 1 TB OK
physicaldrive 3C:1:8 port 3C:box 1:bay 8 SAS 1 TB OK
array E
physicaldrive 4C:2:1 port 4C:box 2:bay 1 SAS 1 TB OK
physicaldrive 4C:2:2 port 4C:box 2:bay 2 SAS 1 TB OK
array F
physicaldrive 4C:2:3 port 4C:box 2:bay 3 SAS 1 TB OK
physicaldrive 4C:2:4 port 4C:box 2:bay 4 SAS 1 TB OK
array G
physicaldrive 5C:2:5 port 5C:box 2:bay 5 SAS 1 TB OK
physicaldrive 5C:2:6 port 5C:box 2:bay 6 SAS 1 TB OK
array H
physicaldrive 5C:2:7 port 5C:box 2:bay 7 SAS 1 TB OK
physicaldrive 5C:2:8 port 5C:box 2:bay 8 SAS 1 TB OK
array I
physicaldrive 6C:3:1 port 6C:box 3:bay 1 SAS 1 TB OK
physicaldrive 6C:3:2 port 6C:box 3:bay 2 SAS 1 TB OK
array J
physicaldrive 6C:3:3 port 6C:box 3:bay 3 SAS 1 TB OK
physicaldrive 6C:3:4 port 6C:box 3:bay 4 SAS 1 TB OK
array K
physicaldrive 7C:3:5 port 7C:box 3:bay 5 SAS 1 TB OK
physicaldrive 7C:3:6 port 7C:box 3:bay 6 SAS 1 TB OK
unassigned
physicaldrive 7C:3:7 port 7C:box 3:bay 7 SAS 1 TB OK
physicaldrive 7C:3:8 port 7C:box 3:bay 8 SAS 1 TB OK
a) The Aim here is to join lines starting with string array and until it hits the pattern starting with the string array again and join the lines and repeat the same for all the lines in the string .
b) The Line containing unassigned and the lines after it should be removed until it hits a line containing the string array at the start of line .
c) In my code , I have removed the line containing unassigned and 2 lines after it , But it should remove any number of lines after unassigned until it matches array at the start of the string .
data
unassinged...
physicaldrive .........
physical dirve .....
physicaldrive......
array
| [reply] [d/l] [select] |
|
|
use strict;
use warnings;
my $row ="";
my $inarray=0;
while (<DATA>) {
chomp;
if (/^array|^unassigned/){
print "$row\n" if $inarray;
$row=$_;
$inarray=m/^array/;
next;
}
next unless $inarray;
$row .= " $_";
}
print "$row\n" if $inarray;
__DATA__
....
"You're only given one little spark of madness. You mustn't lose it." - Robin Williams
| [reply] [d/l] |
|
|
|
|
|
Re: Join multiple lines in a string based on regex.
by trippledubs (Deacon) on Dec 16, 2014 at 04:34 UTC
|
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dump;
my $hashRef;
# See Perldoc perldsc
my $lastSeen;
for (<DATA>) {
length or next;
chomp;
if (!/^physicaldrive/) {
$lastSeen=$_;
} else {
push @{$hashRef->{$lastSeen}},$_;
}
}
my @arrayA = @{$hashRef->{'array A'}};
dd @arrayA;
my $secondDiskArrayA = $hashRef->{'array A'}[1];
dd $secondDiskArrayA;
my $unassignedDisks = $hashRef->{unassigned};
dd $unassignedDisks;
dd $unassignedDisks->[0];
Recommend reading perldsc
| [reply] [d/l] |
|
|
| [reply] |
Re: Join multiple lines in a string based on regex.
by hdb (Monsignor) on Dec 16, 2014 at 09:03 UTC
|
use strict;
use warnings;
use Data::Dumper;
my @data;
while( <DATA> ) {
chop;
if ( /^(array.*|unassigned)$/ ) {
push @data, $1;
} else {
$data[-1] .= " $_";
}
}
print Dumper \@data;
__DATA__
array A
physicaldrive 2C:1:1 port 2C:box 1:bay 1 SAS 1 TB OK
physicaldrive 2C:1:2 port 2C:box 1:bay 2 SAS 1 TB OK
array B
physicaldrive 2C:1:3 port 2C:box 1:bay 3 SAS 1 TB OK
physicaldrive 2C:1:4 port 2C:box 1:bay 4 SAS 1 TB OK
unassigned
physicaldrive 7C:3:7 port 7C:box 3:bay 7 SAS 1 TB OK
physicaldrive 7C:3:8 port 7C:box 3:bay 8 SAS 1 TB OK
| [reply] [d/l] |
|
|
| [reply] |
|
|
Thanks for the reply . $row is the variable where my Command output file handle is for reading . How do I go about capturing the output in the $row variable as I have trimmed lot of lines in the O/P using the scalar variable .
| [reply] |
|
|
Thanks for the reply . Tried the same code , But it fails with the Error Below .
Modification of non-creatable array value attempted, subscript -1 at ./file2.pl line 15, <$fd> line 1.
| [reply] |
|
|
| [reply] |
Re: Join multiple lines in a string based on regex.
by Anonymous Monk on Dec 16, 2014 at 03:43 UTC
|
Could you explain in plain english what steps you as a human would take to solve this problem? If you as a human had to read one line, do something, then read next line... | [reply] |