Как я могу заменить перевод строки в полях csv в кавычках пустым? - PullRequest
0 голосов
/ 07 июня 2018

Иметь большой CSV-файл с некоторыми переводами строк в столбцах в кавычках.Мне нужно запустить скрипт оболочки, sed, awk, perl в порядке и заменяют только переводы строк внутри кавычек пробелом.Конец строки должен быть сохранен, и я не знаю, сколько столбцов или какие поля могут иметь эти встроенные переводы строк.

Дальнейшее изучение файла показывает это в результате cat -v test_lf.csv

"NORTH ?M-^@?OLMSTED"
"PORT?M-^@?ST?M-^@?LUCIE"

в файле CSV, который в Excel показывает разрыв строки, где? M - ^ @?is.

Я бы хотел использовать tr, чтобы заменить все, что есть, пробелом.Как бы я это сделал?Что это за последовательность?

Теперь я обнаружил, что небольшая часть файла выглядит следующим образом в символах и в шестнадцатеричном формате.

13:20:59 [woo:~/Development/scripts] > tail -n 8 test_lf.csv | head -n 1 | od -x
0000000      3431    3136    3439    3039    2c39    542c    4c45    3543
0000020      5f36    3430    2c47    4c46    332c    3934    3338    312c
0000040      3634    3931    3934    3930    222c    4f50    5452    80e2
0000060      53a8    e254    a880    554c    4943    2245    462c    2c4c
0000100      3433    3839    2c33    3737    2c32    3237    2c37    3535
0000120      2c2c    5441    334c    2c51    6e43    7463    222c    6f4e
0000140      80e2    4da8    6773    2c22    2c34    3832    312c    0d35
0000160      000a                                                        
0000161
13:21:50 [woo:~/Development/scripts] > tail -n 8 test_lf.csv | head -n 1 | od -c
0000000    1   4   6   1   9   4   9   0   9   ,   ,   T   E   L   C   5
0000020    6   _   0   4   G   ,   F   L   ,   3   4   9   8   3   ,   1
0000040    4   6   1   9   4   9   0   9   ,   "   P   O   R   T   
      **
0000060   **   S   T   
      **  **   L   U   C   I   E   "   ,   F   L   ,
0000100    3   4   9   8   3   ,   7   7   2   ,   7   2   7   ,   5   5
0000120    ,   ,   A   T   L   3   Q   ,   C   n   c   t   ,   "   N   o
0000140    
      **  **   M   s   g   "   ,   4   ,   2   8   ,   1   5  \r
0000160   \n  

Я на Mac ифайл - это utf-8, а моя локаль - utf-8.Похоже, что байты поменялись местами (little-endian), поэтому шестнадцатеричное 3431 3136 равно 1463 в символьном представлении.Итак, начиная с байта 60 в этом выводе, мы имеем: что-то, S, T, пусто, что-то, что-то, L и в шестнадцатеричном виде это: 53a8 e254 a880 554c, 53 - это S, 54 - это T, а 4c - этоLИтак, существует последовательность e2, a8, 80 между T и L. Это приводит к переводу строки в поле электронной таблицы Excel.
Как мне найти и заменить эти байты пробелом?

Ответы [ 3 ]

0 голосов
/ 07 июня 2018

Предполагая, что символ кавычки является двойной кавычкой ", а escape-символ также является двойной кавычкой, вы можете сделать это с помощью sed, если вы переводите все переводы строки в пробелы, когда число двойных кавычек даже вобразец пространства.Если число нечетное, вам нужно только добавить следующую строку.

sed ':a;/^\([^"]*"[^"]*"\)*[^"]*$/!{N;ba};y/\n/ /' file.csv

детали:

:a    # define the label "a"
/^\([^"]*"[^"]*"\)*[^"]*$/! # if not an even number of quotes
{
    N  # append the next line to the pattern space
    ba # go to label "a"
}
y/\n/ / # translate all line-feeds to spaces

Если кавычки не сбалансированы, поведение по умолчанию не продолжаетсяпоследняя процитированная часть.Вы можете изменить это, написав:

sed ':a;${y/\n/ /;s/$/"/};/^\([^"]*"[^"]*"\)*[^"]*$/!{N;ba};y/\n/ /' file.csv
0 голосов
/ 11 июня 2018

После большого чтения шестнадцатеричных дампов файла csv и изучения различий в том, как Numbers на Mac и Excel на ПК обрабатывают встроенные разрывы, кажется, что простой переносимый способ найти и изменить кодировку для разрывов неСтоит усилий.Если поля данных, содержащие разрывы, заключены в кавычки, то Excel будет читать их нормально, как и read.csv в R.

0 голосов
/ 07 июня 2018

Я бы использовал модуль Perl Text :: CSV

#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use open IO => ':encoding(utf8)';
use open ':std';
use Text::CSV;

my $file = shift @ARGV;
open my $fh, "<", $file or die "cannot open $file: $!\n";

my $csv = Text::CSV->new({binary => 1});

while (my $row = $csv->getline($fh)) {
    my @no_newlines = map {s/\n/ /g; $_} @$row;
    $csv->combine(@no_newlines);
    say $csv->string();
}

close $fh;

И тогда вы можете запустить его так:

/path/to/csvfixer.pl file.csv > fixed.csv
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...