Вопрос или проблема
У меня есть большой файл CSV. В одном из полей содержится ошибка. Эта ошибка отображается как новая строка в файле.
До сих пор я использовал Notepad++ с этой командой для исправления проблемы:
\r”;” => “;”
Как я могу сделать то же самое с помощью sed?
Я уже пробовал
sed -i 's/\r";"https://unix.stackexchange.com/";"/g' /path/file.csv
sed -i 's/^";"https://unix.stackexchange.com/";"/g' /path/file.csv
безуспешно, возможно, кто-то здесь знает правильную команду.
Важно понимать, что sed работает построчно. Что делает sed, это в основном: читает строку в свой буфер без новой строки, выполняет ваши команды на буфере, печатает буфер (если вы не указали флаг -n
), читает следующую строку в свой буфер и т.д. Поэтому, чтобы объединить две строки с помощью sed, требуется явно заставить sed обрабатывать больше одной строки за раз. Для этого команды N
, P
и D
будут вам полезны.
Теперь по вашему конкретному вопросу, чтобы дать вам конкретный и протестированный ответ, мне нужно будет четко понимать вводимые данные, но вот несколько примеров того, что можно сделать :
Это объединит каждые две строки вместе :
sed $'N;s/[\\n\r]//g'
или, если вы уверены, что у вас всегда есть окончания строк \r\n :
sed 'N;s/.\n//'
Для более адаптированного решения к тому, что я понял из вашего вопроса, хотя это не лучший вариант, это должно сработать, если вы используете bash или другую оболочку, которая поддерживает C-экранирование через конструкцию $'str'
:
sed $':l;N;/\r\\n";"/{;s/\r\\n";"https://unix.stackexchange.com/";"/g;n;};bl'
или без конструкции C-стиля и с окончаниями строк \r\n (неговорящее) :
sed ':l;N;/\n";"/{;s/.\n";"https://unix.stackexchange.com/";"/g;n;};bl'
Что оно делает, так это добавляет следующую строку в свой буфер (N
) и проверяет на наличие нужной строки (/\r\\n";"/
). Скрипт выполняет цикл (bl
–> переход к метке :l
, определенной в начале) до тех пор, пока не будет найдено совпадение. Когда совпадение найдено, выполняется скрипт sed между фигурными скобками: заменяются все вхождения \r\\n";"
на ";"
(s/\r\\n";"https://unix.stackexchange.com/";"/g
) и очищается буфер, после чего вводится следующая строка (n
).
Конечно, если файл большой и “ошибки” встречаются редко, это может занять много времени и потреблять много памяти. Если это так, можно использовать другой алгоритм, но мне нужно лучше понять вашу проблему, чтобы быть уверенным, что я правильно её понял.
Также, если вы хотите узнать немного больше о sed, я настоятельно рекомендую этот сайт, который, возможно, не имеет лучшего фона, но является лучшим туториалом по sed на данный момент.
Если вы хотите удалить символы \r
, проще использовать фильтр tr
:
cat file.csv | tr -d '\r' >newfile.csv
или напрямую:
tr -d '\r' <file.csv >newfile.csv
man tr
будет вам полезен. Предупреждение: tr
предназначен для использования как фильтр, читающий из его стандартного ввода, и он не может обрабатывать файл на месте, как sed -i
.
Если вас устраивает решение на Perl:
perl -pe 's/\r";"https://unix.stackexchange.com/";"/g' foo.csv >foo_r.csv
У меня была подобная проблема, но я в итоге использовал немного другой вариант ответа @Fjor.
cat file.csv | tr -d '\n'
.
(Tr – это TRanslate, который обычно является командой поиска/замены, но с -d просто удалит все вхождения строки поиска в одинарных кавычках.)
Я бы предложил это как комментарий к ответу Fjor, если бы у меня была репутация. Ну что ж, вот это так или иначе.
Ответ или решение
Чтобы удалить символы возврата каретки (\r
) из CSV-файла с помощью sed
, можно воспользоваться следующими подходами. Перед тем, как начать, важно помнить, что sed
работает построчно, поэтому удаление символов возврата будет зависеть от структуры файла.
Использование sed
-
Простой вариант для удаления
\r
:
Вы можете использовать следующий командуsed
, чтобы удалить все символы возврата каретки из файла. Эта команда создаст новый файл, в котором\r
будет удален:sed 's/\r//g' файл.csv > новый_файл.csv
В этой команде мы заменяем все вхождения символа
\r
на пустую строку, что фактически приводит к их удалению. -
Удаление
\r
в сочетании с конкретной строкой:
Если вы хотите удалить\r
только из определенного контекста, например, рядом с";"
, вы можете сделать это следующим образом:sed 's/\r";"/";"/g' файл.csv > новый_файл.csv
Эта команда заменяет вхождение
\r";"
на";"
.
Использование tr
В качестве альтернативы можно использовать команду tr
, которая предназначена для замены и удаления символов:
tr -d '\r' < файл.csv > новый_файл.csv
Эта команда удаляет все символы возврата каретки из файла.
Примечания
- Команда
sed
не работает в режиме замены непосредственно в файле (то есть без создания нового файла) без флага-i
(что иногда не рекомендуется по разным причинам). - Имейте в виду, что замена
\r
может привести к тому, что файл перестанет соответствовать формату CSV, поэтому всегда рекомендуется сохранять оригинальный файл до того, как вы будете вносить в него изменения. - Если ваш файл имеет и другую ошибку, где строки смешиваются, и вам необходимо объединить строки, это потребует более сложных команд
sed
для обработки.
Перл Как Альтернатива
Если вы знакомы с Perl, вы можете выполнить аналогичную задачу с помощью следующей команды:
perl -pe 's/\r//g' файл.csv > новый_файл.csv
Такой подход может быть полезен, если вам нужно больше возможностей для обработки текста.
В любом случае, после того как вы выполните вышеуказанные команды, проверьте полученные данные самостоятельно, чтобы удостовериться, что результаты соответствуют вашим ожиданиям.