cut comando, ordem não preservada?

3

Eu tenho um arquivo de amostra: -

[root@localhost base_filters]# cat shortlist
2233|charles harris  |g.m.     |sales     |12/12/52| 90000
9876|bill johnson    |director |production|03/12/50|130000
5678|robert dylan    |d.g.m.   |marketing |04/19/43| 85000
2365|john woodcock   |director |personnel |05/11/47|120000
5423|barry wood      |chairman |admin     |08/30/56|160000

Eu queria inverter os nomes no arquivo para que haja uma vírgula , após o último nome, por exemplo, um nome deve aparecer como harris, charles.

Eu tentei o seguinte comando: -

[root@localhost base_filters]# tr -s ' ' < shortlist | cut -d\| -f2 | cut -d' ' -f2,1
charles harris
bill johnson
robert dylan
john woodcock
barry wood

Quero que o sobrenome apareça primeiro, então especifiquei o campo 2 e, em seguida, 1, mas isso não parece funcionar. Alguma idéia sobre isso?

    
por Ankit 16.04.2013 / 15:03

6 respostas

0

+1 todos, pelo suporte :). Eu encontrei uma solução ainda mais simples: -

[root@localhost base_filters]# paste -d, <(cut -d\| -f2 shortlist| cut -d' ' -f2) <(cut -d\| -f2 shortlist| cut -d' ' -f1)
harris,charles
johnson,bill
dylan,robert
woodcock,john
wood,barry
    
por 18.04.2013 / 06:19
4

Isso é feito facilmente usando awk . Primeiro, imprima o nome e, em seguida, canalize a saída para awk novamente (desta vez usando espaço como o separador de arquivos).

awk -F "|" '{print $2}' extract.txt | awk -F " " '{print $2 "," $1}'
    
por 16.04.2013 / 15:27
4

A função a seguir usará apenas os Bash internos (caso você queira usar o Bash) para fazer o que quiser:

foo () 
{ 
    local filename="$1"

    while IFS='|' read -r pre name suf; do
        l="$pre|${name#* },${name% *}|$suf";
        printf '%s\n' "$l";
    done < "$filename"
}

A variável IFS está definida como | e 'read' lê todas as linhas de cada vez de "$ 1" (seu arquivo) e divide em três partes, $ pre $ name e $ suf , de acordo com o valor do IFS.

$ pre valor é definido para ser o campo antes do nome, $ name é definido para ser o próprio nome que você deseja trocar (o segundo campo) e $ suf é o resto da linha.

Eu uso Expansão de Parâmetros (também pesquise Expansão de Parâmetros em man bash ) para dividir o campo $ name .

"${name#* }" irá cortar o primeiro nome, deixando-nos com o sobrenome.

"${name% *}" cortará o sobrenome, deixando-nos com o primeiro nome.

Uso: foo [/path/to/file.txt]

Exemplo de saída:

nylon100@~$ cat>file.txt
123|first1 last1|foo|bar|date|baz
456|first2 last2|foo|bar|date|baz
789|first3 last3|foo|bar|date|baz

nylon100@~$ foo file.txt
123|last1,first1|foo|bar|date|baz
456|last2,first2|foo|bar|date|baz
789|last3,first3|foo|bar|date|baz
    
por 16.04.2013 / 15:48
3

Sim, o corte não altera a ordem, apenas seleciona dados de cada linha.

Você precisaria usar sed ou awk como:

sed 's/^\([^|]*|\)\([^|]\{1,\}\) \([^ |]\{1,\}\)/,/'
    
por 16.04.2013 / 15:40
2

A página man do cut diz

Selected input is written in the same order that it is read, and is written exactly once.

Então você tem que usar outra ferramenta em vez de cortar. Por exemplo, sed, awk, perl, python ou bash.

    
por 16.04.2013 / 15:38
1

Tente:

tr -s ' ' < shortlist | cut -d\| -f2 | tr '\n' ' ' | tac -s' ' | \
  sed -e 's/^[[:space:]]//' -e 's/  /\n/g' | sort

Ou, se você tiver muitos desses arquivos:

sortnames () {
  tr -s ' ' < $1 | cut -d\| -f2 | tr '\n' ' ' | tac -s' ' | \
    sed -e 's/^[[:space:]]//' -e 's/  /\n/g' | sort
}
    
por 17.04.2013 / 00:32

Tags