@MaxMackie askubuntu.com/questions/88142/… . Não consigo encontrar um mod lá a essa hora, então sinalizei pedindo que eles migrassem, se quisessem; ele já tem uma resposta aceita, então não tenho certeza se eles terão
Michael Mrozek
@MichaelMrozek, hmmm o que geralmente acontece nessas situações? Simplesmente mantemos as duplicatas?
Além de como cortar e reorganizar os campos (abordados nas outras respostas), há a questão dos campos CSV peculiares.
Se seus dados se enquadram nessa categoria "peculiar", um pouco de pré e pós- filtragem podem cuidar disso. Os filtros mostrados abaixo exigem os personagens \x01, \x02, \x03, \x04para não aparecer em qualquer lugar em seus dados.
Aqui estão os filtros envolvidos em um awkdespejo de campo simples .
Nota: o campo cinco possui um layout de "campo entre aspas" inválido / incompleto, mas é benigno no final de uma linha (dependendo do analisador CSV). Mas, é claro, causaria resultados imprevisíveis e problemáticos se fosse trocada de sua posição atual de fim de linha .
Atualizar; user121196 apontou um erro quando uma vírgula precede uma citação à direita. Aqui está a correção.
Os dados
cat <<'EOF'>file
field one,"fie,ld,two",field"three","field,\",four","field,five
"15111 N. Hayden Rd., Ste 160,",""
EOF
field one
"fie,ld,two"
field"three""field,\",four""field,five
"15111 N. Hayden Rd., Ste 160,"""
Aqui está o pré filtro , expandido com comentários.
O filtro de postagem é apenas uma reversão de \x01. \x02, \x03,\x04
sed -r '
s/^/,/# add a leading comma delimiter
s/\\"/\x01/g # obfuscate escaped quotation-mark (\")
s/,"([^"]*)"/,\x02\1\x03/g # obfuscate quotation-marks
s/,"/,\x02/# when no trailing quote on last field :MC # obfuscate commas embedded in quotes
s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g
tMC
s/^,// # remove spurious leading delimiter'
como você excluiria a enésima coluna com base nesse filtro?
user121196
@ user121196 - Como mencionado na sentença de abertura, esta resposta mostra uma maneira de tornar os dados CSV mais consistentes. substituindo termicamente uma vírgula incorporada por aspas por um caractere de token neutro ... e depois revertendo-a para uma vírgula após a movimentação / corte / exclusão. Novamente, como mencionado, a etapa mover / cortar / excluir é substituída por um simples despejo de campo do awk .
precisa saber é o seguinte
1
falha neste caso: "15111 N. Hayden Rd., Ste 160,", ""
user121196
@ user121196: Obrigado por apontar isso. Atualizei a resposta com uma correção.
precisa saber é o seguinte
15
Isso depende se o seu arquivo CSV usa vírgulas apenas para delimitadores ou se você tem loucura como:
campo um, "campo dois", campo três
Isso pressupõe que você esteja usando um arquivo CSV simples:
Removendo uma coluna
Você pode se livrar de uma única coluna de várias maneiras; Eu usei a coluna 2 como exemplo. A maneira mais fácil é provavelmente usar cut, o que permite especificar um delimitador -de quais campos você deseja imprimir -f; isto diz para ele dividir em vírgulas e campo de saída 1 e campos 3 até o final:
$ cut -d,-f1,3-/path/to/your/file
Se você realmente precisar usar sed, você pode escrever uma expressão regular que corresponda aos primeiros n-1campos, o nth e o restante, e pular a saída do nth (aqui né 2, então o primeiro grupo corresponde ao 1tempo :) \{1\}:
$ sed 's/\(\([^,]\+,\)\{1\}\)[^,]\+,\(.*\)/\1\3/'/path/to/your/file
Existem várias maneiras de fazer isso awk, nenhuma delas particularmente elegante. Você pode usar um forloop, mas lidar com a vírgula à direita é uma dor; ignorando que seria algo como:
Em sedesta é essencialmente a mesma expressão como antes, mas você também capturar a coluna de destino e incluir esse grupo várias vezes na substituição:
$ sed 's/\(\([^,]\+,\)\{1\}\)\([^,]\+,\)\(.*\)/\1\3\3\4/'/path/to/your/file
No awkcaminho do loop for, seria algo como (novamente ignorando a vírgula à direita):
Como é CSV, você também precisará BEGIN { FS=","; OFS=","; }.
1
Eu acho que até FS = OFS = "," funcionará.
5
Dado um arquivo delimitado por espaço no seguinte formato:
12345
Você pode remover o campo 2 com o awk da seguinte forma:
awk '{ sub($2,""); print}' file
que retorna
1345
Substitua a coluna 2 pela coluna n, onde apropriado.
Para duplicar a coluna 2,
awk '{ col = $2 " " $2; $2 = col; print }' file
que retorna
122345
Para alternar as colunas 2 e 3,
awk '{temp = $2; $2 = $3; $3 = temp; print}'
que retorna
13245
O awk geralmente é muito bom em lidar com o conceito de campos . Se você está lidando com um CSV, e não com um arquivo delimitado por espaço, pode simplesmente usar
awk -F,
para definir seu campo como vírgula, em vez de um espaço (que é o padrão). Existem vários recursos on-line bons do awk, um dos quais eu listo como fonte abaixo.
Eu não sei muito sobre awk, mas parece saída de espaço-separada, mesmo que o separador de campo é ,(o campo-separadores apenas controla como ele lida com a entrada)
Michael Mrozek
@ MichaelMrozek: sim, é a variável OFS awk que controla o separador de campos de saída.
enzotib
Sim, e como mencionei na minha resposta, você pode passar a opção -F para awk para alterar o delimitador (por exemplo, -F,)
Respostas:
Além de como cortar e reorganizar os campos (abordados nas outras respostas), há a questão dos campos CSV peculiares.
Se seus dados se enquadram nessa categoria "peculiar", um pouco de pré e pós- filtragem podem cuidar disso. Os filtros mostrados abaixo exigem os personagens
\x01
,\x02
,\x03
,\x04
para não aparecer em qualquer lugar em seus dados.Aqui estão os filtros envolvidos em um
awk
despejo de campo simples .Nota: o campo cinco possui um layout de "campo entre aspas" inválido / incompleto, mas é benigno no final de uma linha (dependendo do analisador CSV). Mas, é claro, causaria resultados imprevisíveis e problemáticos se fosse trocada de sua posição atual de fim de linha .
Atualizar; user121196 apontou um erro quando uma vírgula precede uma citação à direita. Aqui está a correção.
Os dados
O código
A saída:
Aqui está o pré filtro , expandido com comentários.
O filtro de postagem é apenas uma reversão de
\x01
.\x02
,\x03
,\x04
fonte
Isso depende se o seu arquivo CSV usa vírgulas apenas para delimitadores ou se você tem loucura como:
Isso pressupõe que você esteja usando um arquivo CSV simples:
Removendo uma coluna
Você pode se livrar de uma única coluna de várias maneiras; Eu usei a coluna 2 como exemplo. A maneira mais fácil é provavelmente usar
cut
, o que permite especificar um delimitador-d
e quais campos você deseja imprimir-f
; isto diz para ele dividir em vírgulas e campo de saída 1 e campos 3 até o final:Se você realmente precisar usar
sed
, você pode escrever uma expressão regular que corresponda aos primeirosn-1
campos, on
th e o restante, e pular a saída don
th (aquin
é 2, então o primeiro grupo corresponde ao1
tempo :)\{1\}
:Existem várias maneiras de fazer isso
awk
, nenhuma delas particularmente elegante. Você pode usar umfor
loop, mas lidar com a vírgula à direita é uma dor; ignorando que seria algo como:Acho mais fácil
substr
gerar o campo 1 e depois usá-lo para extrair tudo após o campo 2:Isso é irritante para colunas mais adiante
Duplicando uma coluna
Em
sed
esta é essencialmente a mesma expressão como antes, mas você também capturar a coluna de destino e incluir esse grupo várias vezes na substituição:No
awk
caminho do loop for, seria algo como (novamente ignorando a vírgula à direita):O
substr
caminho:(tcdyl apresentou um método melhor em sua resposta )
Movendo uma coluna
Eu acho que a
sed
solução segue naturalmente as outras, mas começa a ficar ridiculamente longafonte
awk
é a sua melhor aposta.awk
imprime campos por número, então ...Para remover uma coluna, não a imprima:
Para alterar a ordem:
Redirecionar para um arquivo de saída.
awk
também pode formatar a saída.Saída no formato awk
fonte
BEGIN { FS=","; OFS=","; }
.Dado um arquivo delimitado por espaço no seguinte formato:
Você pode remover o campo 2 com o awk da seguinte forma:
que retorna
Substitua a coluna 2 pela coluna n, onde apropriado.
Para duplicar a coluna 2,
que retorna
Para alternar as colunas 2 e 3,
que retorna
O awk geralmente é muito bom em lidar com o conceito de campos . Se você está lidando com um CSV, e não com um arquivo delimitado por espaço, pode simplesmente usar
para definir seu campo como vírgula, em vez de um espaço (que é o padrão). Existem vários recursos on-line bons do awk, um dos quais eu listo como fonte abaixo.
Fonte para # 3
fonte
awk
, mas parece saída de espaço-separada, mesmo que o separador de campo é,
(o campo-separadores apenas controla como ele lida com a entrada)Isso funcionará para excluir
Entrada
Saída
fonte