Remove all line breaks from only one column of a csv file on Linux

2

I have a csv file with more than 500k of rows and need to remove row breaks from just one column in an efficient way besides exclude all the links that contain it, an excerpt from the file:

"created_at","text","location","name","screen_name","followers_count","friends_count"
"2016-09-17T21:48:10.000Z","MAIS UM CLIENTE REVIVALL #Eleições #Vereador #BH

VÍDEO MARKETING - Solicite uma Proposta Revivall Marketing:... https://t.co/d7qDOguDoA","Belo Horizonte","Objetivo Comunicação","ObjeCom",15,0
"2016-09-17T23:05:01.000Z","Não ia votar no Kalil não. Mas diante de tanta sacanagem nas propagandas políticas meu voto agora é dele. Fazer raiva nas MARIAS.","Belo Horizonte","LEONARDO BARBOSA","LEO_BEAGALO",113,282
"2016-09-17T23:26:10.000Z","RT @brnou3: nossa candidato que legal várias pessoas na rua balançando uma bandeira com seu nome isso conquistou meu voto

disse nenhuma pe…","Belo Horizonte","Júlia","julinhasr",589,306

It has to look like this:

"created_at","text","location","name","screen_name","followers_count","friends_count"
"2016-09-17T21:48:10.000Z","MAIS UM CLIENTE REVIVALL #Eleições #Vereador #BH VÍDEO MARKETING - Solicite uma Proposta Revivall Marketing:... ","Belo Horizonte","Objetivo Comunicação","ObjeCom",15,0
"2016-09-17T23:05:01.000Z","Não ia votar no Kalil não. Mas diante de tanta sacanagem nas propagandas políticas meu voto agora é dele. Fazer raiva nas MARIAS.","Belo Horizonte","LEONARDO BARBOSA","LEO_BEAGALO",113,282
"2016-09-17T23:26:10.000Z","RT @brnou3: nossa candidato que legal várias pessoas na rua balançando uma bandeira com seu nome isso conquistou meu voto disse nenhuma pe…","Belo Horizonte","Júlia","julinhasr",589,306
    
asked by anonymous 07.03.2017 / 01:08

2 answers

7

I know you've requested help for "awk" and "sed" (based on the tags used). But, if you allow me the suggestion, why do not you do it in Python? It's very simple because you treat the file as CSV itself (which also gives you flexibility for any other future needs involving handling these fields).

Here is an example code:

import csv
import re

# Expressão regular ***bem simples*** para identificar URLs HTTP
url_re = 'http[s]:\/\/(www\.)?.*[^ ]'

# Abre o arquivo original para leitura
fin = open('teste.csv', 'r')
# Abre o arquivo de destino para gravação
fout = open('teste2.csv', 'w', newline='')

# Cria os objetos de leitura e gravação de/em CSV (no caso do arquivo de destino,
# força a configuração de todos os campos entre aspas - para manter igual ao seu
# exemplo)
reader = csv.DictReader(fin, delimiter=',')
writer = csv.DictWriter(fout, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL,
                              fieldnames=reader.fieldnames)

# Grava o cabeçalho no arquivo de destino
writer.writeheader()

# Lê o arquivo de entrada linha a linha, e grava no arquivo de saída;
# Aplica as conversões requeridas apenas na coluna 'text'
for row in reader:
    # Substitui as ocorrências de nova linha por um único espaço
    row['text'] = re.sub('\n+', ' ', row['text'])

    # Substitui a ocorrência de URL por um único espaço
    row['text'] = re.sub(url_re, ' ', row['text'])

    # Grava a linha toda na saída
    writer.writerow(row)

fin.close()
fout.close()

In any case, if you prefer to do in sed, for example, just use the same idea (and probably the same regular expressions) to make the exchange.

    
07.03.2017 / 13:51
3

With a file of this size, it is strongly recommended to use a parser / CSV modules .

However assuming that the "" are correct and that there is no \" within the quotation marks we can try to use black magic ...

1 awk and thirst:

(a) Since the first field ("created in") is complex, it is always surrounded by quotation marks. Therefore, " at the beginning of the line is always a log separator.

sed 's/^"/@@"/' in.csv  | 
     awk '{gsub(/(\n|http[^ \n"]*)+/," "); print }' RS="@@"
  • sed 's/^"/@@"/' explicitly marks the record separators with "@@"
  • awk '..awk-program..' RS="@@" processes records repaired by "@@"
  • ...{gsub(/(\n|http[^ \n"]*)+/," ");print} within each record, substitutes \n and URLs by space

2 perl: substitute

According to the same premise (a)

perl -p0e 's/\n(?!")/ /g; s/https?:[^\s"]+/ /g' in.csv
  • s/\n(?!")/ /g; replaces \n with space since there are no quotation marks below
  • s/https?:[^\s"]+/ /g' removes URLs

3 Perl: substitute with eval

This next version is a bit more cryptic:

  • substitute each string in quotation marks for the result of the substitution in the "\ n" and URLS for nothing:
perl -p0e 's{(".*?")}{ $1 =~ s!(\n|https?:[^\s"]+)+! !gr }sge' in.csv
    
07.03.2017 / 14:33