Eu tenho um arquivo csv muito grande. Como você removeria o último ,
com sed (ou similar)?
...
[11911,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11912,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11913,0,"BUILDER","2014-10-15","BUILDER",0,0],
]
Saída desejada
...
[11911,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11912,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11913,0,"BUILDER","2014-10-15","BUILDER",0,0]
]
O comando sed a seguir excluirá a última ocorrência por linha, mas eu quero por arquivo.
sed -e 's/,$//' foo.csv
Isso também não funciona
sed '$s/,//' foo.csv
Respostas:
Usando
awk
Se a vírgula estiver sempre no final da segunda à última linha:
Usando
awk
ebash
Usando
sed
Para OSX e outras plataformas BSD, tente:
Usando
bash
fonte
sed: 1: "x;${s/,$//;p;x}; 2,$ p": extra characters at the end of x command
sed
e geralmente é diferente de maneiras sutis. Eu não tenho acesso a OSX para testar isso, mas por favor tentesed -n -e x -e '${s/,$//;p;x;}' -e '2,$ p' input
Simplesmente, você pode tentar o comando Perl de uma linha abaixo.
Explicação:
,
Corresponde a uma vírgula.(?!.*,)
Lookahead negativo afirma que não haveria uma vírgula depois dessa vírgula correspondente. Portanto, corresponderia à última vírgula.s
E o mais importante é os
modificador DOTALL, que também faz com que o ponto corresponda até aos caracteres de nova linha.fonte
perl -0777 -pi -e 's/(.*),(.*?)/\1\2/s'
. Isso funciona porque o primeiro.*
é ganancioso, enquanto o segundo não é.Isso deve remover apenas a última ocorrência de a
,
em qualquer arquivo de entrada - e ainda imprimirá aqueles nos quais a,
não ocorre. Basicamente, ele armazena em buffer sequências de linhas que não contêm vírgula.Quando encontra uma vírgula, troca o buffer de linha atual pelo buffer de retenção e, dessa maneira, imprime simultaneamente todas as linhas que ocorreram desde a última vírgula e libera seu buffer de retenção.
Eu estava apenas pesquisando meu arquivo de histórico e encontrei o seguinte:
É realmente muito bom. Sim, ele usa
eval
, mas nunca lhe passa nada além de uma referência numérica a seus argumentos. Ele criased
scripts arbitrários para lidar com uma última correspondência. Eu vou te mostrar:Isso imprime o seguinte em stderr. Esta é uma cópia da
lmatch
entrada de:O
eval
subshell ed da função repete todos os argumentos uma vez. À medida que caminha sobre eles, itera um contador adequadamente, dependendo do contexto de cada opção e ignora muitos argumentos para a próxima iteração. A partir de então, ele faz uma de algumas coisas por argumento:$a
a$o
.$a
é atribuído com base no valor$i
incrementado pela contagem de argumentos para cada argumento processado.$a
é atribuído um dos dois seguintes valores:a=$((i+=1))
- é atribuído se uma opção curta não tem seu argumento anexado ou se a opção era longa.a=$i#-?
- este é atribuído se a opção é curta e não têm a sua arg anexado a ele.a=\${$a}${1:+$d\${$(($1))\}}
- Independentemente da atribuição inicial,$a
o valor de sempre é colocado entre chaves e - em um-s
caso - algumas vezes$i
é incrementado mais um campo adicional e delimitado é anexado.O resultado é que
eval
nunca é passada uma string que contém incógnitas. Cada um dos argumentos da linha de comando é referido por seu número numérico - mesmo o delimitador que é extraído do primeiro caractere do primeiro argumento e é a única vez em que você deve usar qualquer caractere que não tiver escapado. Basicamente, a função é um gerador de macro - nunca interpreta os valores dos argumentos de nenhuma maneira especial, porquesed
pode (e será, é claro) facilmente manipular isso quando analisa o script. Em vez disso, apenas organiza sensivelmente seus argumentos em um script viável.Aqui estão algumas saídas de depuração da função no trabalho:
E assim
lmatch
pode ser usado para aplicar facilmente expressões regulares aos dados após a última correspondência em um arquivo. O resultado do comando que eu executei acima é:... que, dado o subconjunto da entrada de arquivo que se segue à última vez em que
/^.0/
é correspondido, aplica as seguintes substituições:sdd&&&&d
- substitui$match
-se 4 vezes.sd'dsqd4
- a quarta aspas simples após o início da linha desde a última partida.sd"d\dqd2
- Idem, mas para aspas duplas e globalmente.E assim, para demonstrar como alguém pode usar
lmatch
para remover a última vírgula de um arquivo:RESULTADO:
fonte
-m
opção e a tornei obrigatória, mudei para vários argumentos para re e repl-s
e também implementei o manuseio adequado do delimitador. Eu acho que é à prova de balas. I utilizado com sucesso tanto um espaço e uma única citação como delimitador,Se a vírgula não estiver na penúltima linha
Usando
awk
etac
:O
awk
comando é simples de fazer a substituição na primeira vez que o padrão é visto.tac
inverte a ordem das linhas no arquivo, portanto, oawk
comando acaba removendo a última vírgula.Me disseram isso
pode ser mais eficiente.
fonte
Se você pode usar
tac
:fonte
consulte /programming/12390134/remove-comma-from-last-line
Isso é trabalhado para mim:
Minha melhor maneira é remover a última linha e depois de remover a vírgula, adicione o] char novamente
fonte
Tente com abaixo
vi
:Explicação:
$-1
selecione a penúltima linhas
substituir\(,\)\(\_s*]\)
encontre uma vírgula seguida por]
e separada por espaços ou nova linha\2
substitua por\(\_s*]\)
espaços ou nova linha seguidos por]
fonte
Tente com o
sed
comando abaixo .fonte