2013-11-10 3 views
0

모든 탭 분할하지 않을 수 있습니다분할() 나는 한 줄의 파일이

$ od -c testData.txt 
0000000 6 7 7 7 1 0 \t 0 \t 1 \t L P A Y \t 
0000020 F 6 3 5 P 3 B \t L P A Y 0 0 0 0 
0000040 1 \t F R M \t H O U S T O N  G R 
0000060 O U P  ( a k a  C O R P O R A 
0000100 T E  A D V O C A T E S  I N C 
0000120 . )  T H E \t \t \t \t S a c r a m 
0000140 e n t o \t C A \t 9 5 8 1 4 - 2 8 
0000160 2 5 \t ( 9 1 6 )  4 4 7 - 9 8 8 
0000200 4 \t \t 6 4 9 9 . 9 8 \t 1 7 . 1 9 
0000220 \t 0 \t \t 6 5 1 7 . 1 7 \t 3 9 3 0 
0000240 9 . 2 3 \t N \t \t \t \r \n      
0000253 

을 내가 가지고있는 한 가지 않는 스크립트 : 나는 맥 오전

#!/usr/bin/perl 
$line = <STDIN>; 
@p = split '\t', $line; 
chomp(@p); 
for ($idx = 0; $idx < scalar(@p); $idx++) { print $idx.": \"".$p[$idx]."\"\n"; } 
exit(0); 

을 OS X 10.8.5 및 주식 perl (perl 5, version 12, darwin-thread-multi-2level 용으로 만들어진 Subversion 4 (v5.12.4))을 사용합니다.

데이터를 col로 파이프하지 않으면 라인 끝에서 글리치가 발생합니다. 그런 다음 split() 함수는 몇 개의 탭을 무시합니다. 모두가 아니라 일부. 정말. 성가신.

$ ./testSplit < testData.txt 
0: "677710" 
1: "0" 
2: "1" 
3: "LPAY" 
4: "F635P3B" 
5: "LPAY00001" 
6: "FRM" 
7: "HOUSTON GROUP (aka CORPORATE ADVOCATES INC.) THE" 
8: "" 
9: "" 
10: "" 
11: "Sacramento" 
12: "CA" 
13: "95814-2825" 
14: "(916) 447-9884" 
15: "" 
16: "6499.98" 
17: "17.19" 
18: "0" 
19: "" 
20: "6517.17" 
21: "39309.23" 
22: "N" 
23: "" 
24: "" 
"5: " 
$ 

위의 마지막 줄에 약간의 결함이 있습니다.

$ col < testData.txt | ./testSplit 
0: "677710" 
1: "0" 
2: "1" 
3: "LPAY" 
4: "F635P3B LPAY00001" 
5: "FRM" 
6: "HOUSTON GROUP (aka CORPORATE ADVOCATES INC.) THE" 
7: "" 
8: "" 
9: "" 
10: "Sacramento" 
11: "CA" 
12: "95814-2825" 
13: "(916) 447-9884" 
14: "" 
15: "6499.98 17.19" 
16: "0" 
17: "" 
18: "6517.17 39309.23" 
19: "N" 
$ 

도대체!

답변

6

사실,이 탭을 무시하는 것 col가 (이 공간에 그 중 일부를 변환하는 것)입니다 :

$ diff -u <(od -c testData.txt) <(col <testData.txt | od -c) 
--- /dev/fd/63 2013-11-10 00:06:29.532490383 -0600 
+++ /dev/fd/62 2013-11-10 00:06:29.532490383 -0600 
@@ -1,12 +1,12 @@ 
0000000 6 7 7 7 1 0 \t 0 \t 1 \t L P A Y \t 
-0000020 F 6 3 5 P 3 B \t L P A Y 0 0 0 0 
+0000020 F 6 3 5 P 3 B  L P A Y 0 0 0 0 
0000040 1 \t F R M \t H O U S T O N  G R 
0000060 O U P  ( a k a  C O R P O R A 
0000100 T E  A D V O C A T E S  I N C 
0000120 . )  T H E \t \t \t \t S a c r a m 
0000140 e n t o \t C A \t 9 5 8 1 4 - 2 8 
0000160 2 5 \t ( 9 1 6 )  4 4 7 - 9 8 8 
-0000200 4 \t \t 6 4 9 9 . 9 8 \t 1 7 . 1 9 
+0000200 4 \t \t 6 4 9 9 . 9 8  1 7 . 1 9 
-0000220 \t 0 \t \t 6 5 1 7 . 1 7 \t 3 9 3 0 
+0000220 \t 0 \t \t 6 5 1 7 . 1 7  3 9 3 0 
-0000240 9 . 2 3 \t N \t \t \t \r \n 
+0000240 9 . 2 3 \t N \n 
-0000253 
+0000247 

은 실제 문제를 해결하려면, 당신은 \r 문자를 제거해야합니다. chomp은 그렇게하지 않습니다. 필드 25는 본질적으로 print qq{25: "\r"\n}입니다. \r은 커서를 왼쪽 여백으로 이동시켜 "2을 덮어 씁니다.

#!/usr/bin/perl 
use strict; 
use warnings; 

binmode STDIN, ':crlf'; 

my $line = <STDIN>; 
chomp($line); 
my @p = split /\t/, $line, -1; 
for my $idx (0 .. $#p) { print $idx.": \"".$p[$idx]."\"\n"; } 
exit(0); 

주요 변경 : 읽을 때

  1. binmode STDIN, ':crlf'이 CRLF-> LF 번역 켜집니다

    은 여기에 정리 된 버전입니다. 그러면 \r이 제거됩니다.

  2. 개별적인 부분이 아닌 라인을 강조하십시오. chomp은 줄 끝 문자 만 제거하기 때문에 치명적이지는 않지만 실제로 원하는 문자가 chomp $line 일 때 @p의 모든 요소를 ​​채우는 데 시간이 낭비됩니다.
  3. -1을 split에 추가하는 중입니다. 이렇게하면 빈 필드가 끝에 유지됩니다. 그렇지 않은 경우 출력은 필드 22에서 멈 춥니 다. (꼬리표 \r이 마지막 문자를 의미 했으므로 빈 필드는 표시되지 않았습니다.)
  4. for 루프를 변경하면 0 .. $#p을 사용할 필요가 없습니다. 그것은 더 간단합니다.
  5. strictwarnings을 사용하는 것은 항상 좋은 생각입니다. 이를 위해 my 문을 여러 개 삽입해야했습니다.
+0

binmode 문이 '\ r'을 제거하지 않았습니다. 하지만 수동으로 할 수 있습니다. 다른 모든 것들에 대해 알아보십시오. 훨씬 고맙습니다! –

관련 문제