0

1行のファイルがあります:

 $ 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

私は1つのことを行うスクリプトを持っています:

 #!/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);

私は Mac OS X 10.8.5 を使用しており、標準の perl (darwin-thread-multi-2level 用に構築された perl 5、バージョン 12、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"
 $

なんてこった!

4

1 に答える 1

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行末文字を削除するだけなので、これは致命的ではありませんが@p、本当に必要なときにすべての要素をむさぼり食うのは時間の無駄ですchomp $line
  3. に -1 を加算しsplitます。これにより、空のフィールドが最後に保持されます。そうしないと、出力はフィールド 22 で停止します\r
  4. for使用するループを変更する0 .. $#p必要はありません。単純です。
  5. strictandを使用warningsすることは常に良い考えです。myこれには、いくつかのステートメントを挿入する必要がありました。
于 2013-11-10T01:04:07.590 に答える