किसी भी पैक समाधान के बारे में पता नहीं है, लेकिन कुछ बहुत लचीला नहीं यह सोचते हैं आप फ़ाइल पर दो गुजरता कर सकते हैं करने के लिए काफी सरल है: (निम्न आंशिक रूप से Perlish है स्यूडोकोड उदाहरण)
- धारणा: डेटा स्पेस हो सकते हैं और CSV आला उद्धृत नहीं है वहाँ अगर एक अंतरिक्ष - यदि यह स्थिति नहीं है, बस
Text::CSV(_XS)
का उपयोग करें।
- धारणा: फ़ॉर्मेटिंग के लिए उपयोग किए जाने वाले कोई भी टैब नहीं।
- तर्क "स्तंभ विभाजक" को रिक्त स्थान के साथ 100% आबादी वाली ऊर्ध्वाधर पंक्तियों के लगातार सेट के रूप में परिभाषित करता है।
- यदि दुर्घटना से प्रत्येक पंक्ति में एक स्थान होता है जो ऑफसेट एम वर्णों पर डेटा का हिस्सा होता है, तो तर्क ऑफसेट एम को कॉलम सेपरेटर होने पर विचार करेगा, क्योंकि यह किसी भी बेहतर तरीके से नहीं जान सकता है। एकमात्र तरीका यह बेहतर तरीके से जान सकता है कि यदि आपको कम से कम एक्स रिक्त स्थान होने के लिए कॉलम अलगाव की आवश्यकता होती है जहां X> 1 - उसके लिए दूसरा कोड खंड देखें।
नमूना कोड:
my $INFER_FROM_N_LINES = 10; # Infer columns from this # of lines
# 0 means from entire file
my $lines_scanned = 0;
my @non_spaces=[];
# First pass - find which character columns in the file have all spaces and which don't
my $fh = open(...) or die;
while (<$fh>) {
last if $INFER_FROM_N_LINES && $lines_scanned++ == $INFER_FROM_N_LINES;
chomp;
my $line = $_;
my @chars = split(//, $line);
for (my $i = 0; $i < @chars; $i++) { # Probably can be done prettier via map?
$non_spaces[$i] = 1 if $chars[$i] ne " ";
}
}
close $fh or die;
# Find columns, defined as consecutive "non-spaces" slices.
my @starts, @ends; # Index at which columns start and end
my $state = " "; # Not inside a column
for (my $i = 0; $i < @non_spaces; $i++) {
next if $state eq " " && !$non_spaces[$i];
next if $state eq "c" && $non_spaces[$i];
if ($state eq " ") { # && $non_spaces[$i] of course => start column
$state = "c";
push @starts, $i;
} else { # meaning $state eq "c" && !$non_spaces[$i] => end column
$state = " ";
push @ends, $i-1;
}
}
if ($state eq "c") { # Last char is NOT a space - produce the last column end
push @ends, $#non_spaces;
}
# Now split lines
my $fh = open(...) or die;
my @rows =();
while (<$fh>) {
my @columns =();
push @rows, \@columns;
chomp;
my $line = $_;
for (my $col_num = 0; $col_num < @starts; $col_num++) {
$columns[$col_num] = substr($_, $starts[$col_num], $ends[$col_num]-$starts[$col_num]+1);
}
}
close $fh or die;
अब, अगर आप स्तंभ जुदाई की आवश्यकता होती है जहाँ X> 1, यह भी संभव है लेकिन स्तंभ वाले स्थानों की पार्सर एक सा होने की जरूरत है कम से कम X रिक्त स्थान होने के लिए और अधिक जटिल:
# Find columns, defined as consecutive "non-spaces" slices separated by at least 3 spaces.
my $min_col_separator_is_X_spaces = 3;
my @starts, @ends; # Index at which columns start and end
my $state = "S"; # inside a separator
NEXT_CHAR: for (my $i = 0; $i < @non_spaces; $i++) {
if ($state eq "S") { # done with last column, inside a separator
if ($non_spaces[$i]) { # start a new column
$state = "c";
push @starts, $i;
}
next;
}
if ($state eq "c") { # Processing a column
if (!$non_spaces[$i]) { # First space after non-space
# Could be beginning of separator? check next X chars!
for (my $j = $i+1; $j < @non_spaces
|| $j < $i+$min_col_separator_is_X_spaces; $j++) {
if ($non_spaces[$j]) {
$i = $j++; # No need to re-scan again
next NEXT_CHAR; # OUTER loop
}
# If we reach here, next X chars are spaces! Column ended!
push @ends, $i-1;
$state = "S";
$i = $i + $min_col_separator_is_X_spaces;
}
}
next;
}
}
प्रदान करते हैं और उदाहरण दें। – DVK
मैंने एक समाधान प्रदान किया, लेकिन यह छह कॉलम का उत्पादन करेगा। क्या आप एक धारणा बना रहे हैं taht कॉलम विभाजक होना चाहिए> 1 स्थान? – DVK
नहीं, लेकिन हम मान सकते हैं कि मुझे कॉलम हेडर स्ट्रिंग्स पता है, और कॉलम डेटा हेडर के नीचे ठीक से संरेखित है। – Thilo