Como usar o comando cut para obter o primeiro e último elementos de uma linha?

3

Eu pedi quase o mesmo pergunta já , mas, desta vez, quero recuperar os elementos X mais recentes de uma linha de um arquivo CSV. Por exemplo, com um arquivo de entrada como este:

1;foo;bar;baz;x;y;z
2;foo;bar;baz;x;y;z
3;foo;bar;baz;x;y;z

Qual seria o comando (eventualmente usando cut ) para obter as duas últimas colunas, então eu recebo:

y;z
y;z
y;z

Na verdade, meu objetivo real é recuperar os 3 primeiros e os últimos 2 campos de cada linha, então fico:

1;foo;bar;y;z
2;foo;bar;y;z
3;foo;bar;y;z

Infelizmente, não consigo usar um comando como cut -d \; -f 1-3,10-11 (se houver 11 elementos na linha), porque o arquivo CSV não respeita o formato CSV real . De fato, alguns campos no meio das linhas são criptografados , e seu valor criptografado às vezes contém um ; de caracteres (e, é claro, eles não são agrupados em " ). Em outras palavras, minhas falas podem parecer assim:

1;foo;bar;#@$"é&^l#;baz;x;y;z
2;foo;bar;#¤=é;)o'#;baz;x;y;z
3;foo;bar;#]]'~é{{#;baz;x;y;z

e como você pode ver, na segunda linha, há um caractere ; adicional, então não posso usar aqui um comando como cut -d \; -f 1-3,7-8 , porque se retornará isso, o que está errado:

1;foo;bar;y;z
2;foo;bar;x;y  (-> Wrong here, there is a shift)
3;foo;bar;y;z

Então, como posso usar o cut para resolver meu problema?

Obrigado

ps: Eu sou especialmente apaixonado pelo comando cut , então se você tem um comando que faz o que eu quero mas não é cut , então está tudo bem também:)

Editar Parece importante notar que a máquina é bem antiga: uname -a dê esta mensagem:

SunOS ###### 5.10 Generic_142900-05 sun4u sparc SUNW,Sun-Fire-V240

e alguns comandos podem não estar presentes (como rev )

    
por Romain Linsolas 07.01.2013 / 15:32

3 respostas

5

Na sua versão de SunOS nawk (ou quanto a awk ) deve ser capaz de fazer o truque

 nawk -F';' 'BEGIN{OFS=";"}{print($1,$2,$3,$(NF-1),$(NF))}' file.txt 
    
por 07.01.2013 / 17:22
5

Aqui está uma solução de múltiplos comandos para recuperar os 3 primeiros e os 2 últimos campos usando apenas cut , rev (para reversão) e shell-builtins:

while read line
do
    first=$(echo -n "$line" | cut -d ";" -f -3)
    second=$(echo -n "$line" | rev | cut -d ";" -f -2 | rev)
    echo "$first;$second"
done < my_file

Estas declarações também podem ser colocadas em uma única linha, é claro.

EDITAR:

Reuni algumas alternativas de uma linha para rev (que omitem a impressão do final '\ n' ):

python: python -c "import sys; sys.stdout.write(raw_input()[::-1])

perl: perl -ne 'chomp;print scalar reverse;'

e há muito mais possibilidades de reverter uma string . Talvez alguns deles funcionem no seu sistema.

    
por 07.01.2013 / 15:42
2
% cat a
1;foo;bar;#@$"é&^l#;baz;x;y;z
2;foo;bar;#¤=é;)o'#;baz;x;y;z
3;foo;bar;#]]'~é{{#;baz;x;y;z
% sed -r 's,^(([^;]+;){3}).*;([^;]+;[^;]+)$,,' < a
1;foo;bar;y;z
2;foo;bar;y;z
3;foo;bar;y;z
    
por 07.01.2013 / 15:46