Como contar o número de linhas em um arquivo UTF-16LE / CR-LF / BOM?

5

O pensamento imediato é wc , mas então o próximo pensamento não tão imediato é ... O wc do * nix é puramente para * nix terminações de linha \ x0a? ... Parece que sim.

Eu já passei por isso, mas sinto que pode / deve ser uma maneira mais simples do que trabalhar em um hex-dump do original.

Aqui está a minha versão, mas ainda há uma misteriosa discrepância nos registros. wc reporta mais 1 0a do que a soma do CRLF + 0a deste script.

 file="nagaricb.nag"
 echo Report on CR and LF in UTF-16LE/CR-LF
 echo =====================================
 cat "$file" | # a useles comment, courtesy of cat 
   xxd -p -c 2 |
     sed -nr '
       /0a../{
           /0a00/!{
               i ‾‾'0a:   embedded in non-newline chars       
               b
           }
       }
       /0d../{
           /0d00/!{
               i ‾‾'0d:   embedded in non-newline chars       
               b
           }
       }
       /0a00/{
           i ‾‾'CR: found stray 0a00       
           b
        }
       /0d00/{
           N
           /0d00\n0a00/{
               i ‾‾'CRLF: found as normal newline pairs
               b
           }
           i ‾‾'LF: found stray 0d00
        }' |
         sort |
           uniq -c
 echo "  ====="
 printf '  %s ‾‾'wc\n' $(<"$file" wc -l)

Saída

Report on CR and LF in UTF-16LE/CR-LF
=====================================
    125 ‾‾'0a:   embedded in non-newline chars       
    407 ‾‾'0d:   embedded in non-newline chars       
  31826 ‾‾'CRLF: found as normal newline pairs
  =====
  31952 ‾‾'wc

Existe alguma maneira mais padrão / simples de fazer isso?

    
por Peter.O 31.05.2012 / 13:03

3 respostas

5

Aqui está um script perl que abre arquivos (dados como argumentos de linha de comando) em UTF-16 (endianness detectado via BOM) e conta as linhas.

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

while (my $file = shift @ARGV) {
    my $fh;
    if (!open($fh, '<:encoding(UTF-16)', $file)) {
        print STDERR "Failed to open [$file]: $!\n";
        next;
    }
    my $count = 0;
    $count++ while (<$fh>);
    print "$file: $count\n";
    close $fh;
}

(morre se a lista de materiais não for compreendida).

    
por 31.05.2012 / 15:42
6

Eu converteria o arquivo para UTF-8 com finais de linha LF, para que eu possa usar diretamente as ferramentas nativas:

$ iconv -f UTF-16LE -t UTF-8 myfile.txt | dos2unix | wc -l

A parte dos2unix é o bit mais complicado. Existem muitas variantes dessa ferramenta flutuando, e nem todas elas sabem como ser usadas em um pipeline. Às vezes é chamado de outra coisa, como d2u .

    
por 31.05.2012 / 15:41
2

Se você possui dos2unix version > = 7.1, você pode usar a opção -i para obter informações sobre o número de quebras de linha. Arquivos UTF-16 também são suportados. Quando o arquivo tem uma lista de materiais, o dos2unix detecta automaticamente que é UTF-16, LE ou BE. Quando o arquivo não tem BOM, você pode usar a opção -ul para dizer que é UTF-16LE (ou -ub para UTF-16BE).

dos2unix -i imprime o número de quebras de linha DOS, Unix e Mac nessa ordem. Exemplo (com BOM):

$ dos2unix -i utf16le.txt
      50       0       0  UTF-16LE  text    utf16le.txt

Sem lista técnica:

$ dos2unix -ul -i utf16len.txt
      50       0       0  no_bom    text    utf16len.txt

Veja o manual para mais informações.

    
por 26.11.2015 / 09:36