Что хороший путь состоит в том, чтобы отфильтровать текстовый файл для удаления пустых строк?

С ударом можно получить желаемый эффект, поместив следующее в ~/.bashrc файл:

bind '"\C-w":backward-kill-word'

Хит CTRL+V и Ваше сочетание клавиш для наблюдения то, на что это похоже для эмулятора терминала. Например, CTRL+bksp может быть интерпретирован отличающийся на различных терминалах, например. ^H или ^?. ^ символ совпадает с CTRL.

11
29.11.2012, 01:41
11 ответов

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

require 'csv'
c = CSV.open("outfile1.csv", "w")
CSV.foreach("data.csv", :encoding => 'windows-1251:utf-8') do |row|
  row = row.map { |a| a.class == String ? a.gsub(/\r/, '') : a}
  c << row
end
c.close

Благодарен за то, что все помогают!

3
27.01.2020, 19:56

Можно использовать grep's -v (инвертируйте соответствие), режим, чтобы сделать это:

grep -v '^$' old-file.csv > new-file.csv

Обратите внимание, что это должны быть различные файлы, из-за того, как оболочка перенаправляет работу. Выходной файл открыт (и освобожден), прежде чем входной файл будет считан. Если у Вас есть moreutils (не по умолчанию на Mac OS X), можно использовать sponge работать вокруг этого:

grep -v '^$' file.csv | sponge file.csv

Но конечно, затем Вам приходится тяжелее, возвращаясь, если что-то идет не так, как надо.

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

egrep -v '^[[:space:]]*$' old-file.csv > new-file.csv

Это проигнорирует пустые строки, а также строки, содержащие только пробел. Можно, конечно, сделать то же sponge преобразование на нем.

11
27.01.2020, 19:56
  • 1
    Спасибо.... Не удалил пустых строк... Возможно, ^ $ не соответствует? Но строки пусты насколько я знаю. Помните, что это - cdv, созданный Excel на Mac, который говорит что-нибудь? (Не убегайте, крича, потому что я сказал, что Excel :) –  pitosalas 28.11.2012, 19:16
  • 2
    @pitosalas Они - вероятно, не пустые строки. Попытайтесь изменить его на egrep -v '^[[:space:]]*$' ... обратите внимание, что grep-> egrep и странный новый шаблон –  derobert 28.11.2012, 19:28
  • 3
    не работал. Удаленный набор двойных кавычек и сделанный путаницей... –  pitosalas 28.11.2012, 19:55
  • 4
    @pitosalas я не уверен, как он удалил бы двойные кавычки. Это должно только смочь удалить пробел. И действительно, это - то, что это делает, когда я тестирую его на данных в качестве примера, Вы отправили... –  derobert 28.11.2012, 19:59
  • 5
    @pitosalas, мог Вы проверять, выкладывает ли любая из этих команд что-то, что выглядит разумным (в противоположность мусору): iconv -f utf16le file.csv | head или iconv -f utf16be file.csv | head –  derobert 28.11.2012, 20:01

Самая легкая опция справедлива grep .. Здесь, точка означает, "соответствуют чему-либо", поэтому если строка пуста, она не подобрана. Otherwhise это печатает целую строку, как.

8
27.01.2020, 19:56

Удалить пустые строки, на месте, с ksh93:

sed '/./!d' file 1<>; file

<>; оператор перенаправления характерен для ksh93 и совпадает со стандартом <> оператор за исключением того, что ksh усекает файл после команды, завершился.

sed '/./!d' замысловатый путь состоит в том, чтобы записать grep ., но к сожалению GNU grep, по крайней мере, жалуется, указывает ли его stdout на тот же файл как его stdin. Вы сказали бы, что можно было записать:

grep . file | cat 1<>; file

Но к сожалению, существует ошибка в ksh93 (по крайней мере, моя версия (93u +)), в котором файл, кажется, является усеченным для обнуления длины в этом случае.

grep . file | { cat; } 1<>; file

Кажется, работает вокруг той ошибки, но теперь, это является намного более замысловатым, чем команда sed.

6
27.01.2020, 19:56
  • 1
    Объедините свои ответы в одну хорошо отформатированную запись с кратким руководством по по тому, когда каждое решение должно будет использоваться. Разные подходы к различным проблемам, которые все смешанные в плавании ответов имеют, делают этот вопрос определенной аварией для чтения. –  Caleb 05.12.2012, 12:21
  • 2
    @Caleb, Все это сводится к вопросу, являющемуся очень неясным, таким образом, все общие ответы для различных интерпретаций вопроса. Для каждого ответа я пытался сказать, на какой вопрос он пытается ответить. –  Stéphane Chazelas 05.12.2012, 13:00
  • 3
    Просто к вашему сведению: Испытанный awk '/./' file 1<>; file который работавший. Мне это еще более ясно, чем sed '/./!d' –  grebneke 06.03.2014, 19:53

Вот a Perl острота для него:

perl -pi -e 's/^\s*\n//' yourfile

Править: Улучшенный код на основе комментариев ruakh ниже.

5
27.01.2020, 19:56
  • 1
    Или perl -ni -e '/./ and print' yourfile –  derobert 28.11.2012, 19:13
  • 2
    @peterph $ привязка (т.е. нулевая ширина), таким образом, она исключает новую строку. Относительно лишнего пространства, это - причина, которую я добавил /x Я не хотел Perl пытаться интерполировать '$\\' в огромное спасибо regex –  Joseph R. 28.11.2012, 19:37
  • 3
    Вам не нужно $, учитывая, что Вы имеете \n. (Кроме того - Вам не нужно \n, учитывая, что Вы имеете \s* и $; но я думаю s/^\s*\n// делает это более ясным, что новая строка удалена.) Вам также не нужно /m; это не имеет никакого эффекта на эту команду. И после того как Вы избавляетесь от $ и пространство, Вам не будет нужно /x. –  ruakh 28.11.2012, 23:20
  • 4
    @JosephR.: \n самостоятельно может быть удален; то, что Вы не можете сделать, удаляют обоих $ и \n. Так s/^\s*// имел бы проблему, которую Вы описываете, но s/^\s*$// был бы прекрасен, из-за \s* и $. (Вы видите то, что я имею в виду?) –  ruakh 29.11.2012, 01:34
  • 5
    @JosephR.: То, что происходит, $ может соответствовать перед новой строкой (при условии, что любой /m флаг включен, или новая строка является самым последним символом строки или обоих), но это может также соответствовать концу строки. Например, "abc" =~ m/^abc$/ верно. В случае \s*$, \s* является достаточно жадным для съедения новой строки, и затем $ соответствует концу строки. (Но я думаю s/^\s*\n// более ясно, так или иначе, таким образом, Ваш ответ очень хорошо, как это теперь.) –  ruakh 29.11.2012, 01:53

На основе разъяснения в комментариях к Вашему вопросу, чему-то как:

awk -v RS= -v ORS= 1

может сделать то, что Вы хотите.

Пустой разделитель записей является особым случаем, который говорит awk это записывает, должны быть абзацы (разделенный последовательностями пустых строк). Установка выходного разделителя записей к пустой строке также означает, что содержание тех абзацев (без разделителей) должно быть связано. 1 просто истинное условие распечатать каждую запись.

Это однако опустило бы запаздывающую новую строку, таким образом, Вы могли сделать:

awk -v RS= -v ORS= '1;END{if (NR) printf "\n"}'
5
27.01.2020, 19:56
awk '
    length == 0 {next} 
    /^[^"]/ && /"$/ {print; next} 
    {printf("%s", $0)}
' filename

производит

"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
2
27.01.2020, 19:56

Я нашел идею для возможного решения на stackoverflow.

sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv

Необходимо, вероятно, скопировать файл CSV прежде, чем протестировать его, но по крайней мере для примера Вы, если это работает безупречно.

Хорошее объяснение о внутренних работах этого выражения предлагается в ответе, я просто отредактировал его для поиска строк, которые не заканчиваются a " ([^"]\n).

2
27.01.2020, 19:56

Если от Вашего собственного ответа Вы хотите удалить символы новой строки, содержавшие в заключенных в кавычки строках, Вы могли сделать:

 perl -0777 -pe 's/".*?"/$_=$&;s:\n::g;$_/gse'

Вы могли также использовать perl's использования -i отметьте для редактирования файлов на месте.

 perl -0777 -pe 's/".*?"/$_=$&;s:\n::g;$_/gse' file1 file2...

Или с GNU awk:

 awk -v RS=\" 'NR%2==0 {gsub("\n","")}; {printf "%s", $0 RT}'

или:

 awk -vRS=\" '1-NR%2{gsub("\n","")}{ORS=RT}1'

(если Вы конкурируете за самый короткий),

Обратите внимание, что они предполагают, что нет никаких завершенных символов двойной кавычки во входе.

1
27.01.2020, 19:56

Похоже в действительности, что Вы хотите больше, чем удаление пустых строк, но удаляете каждую последовательность 2 или больше символов новой строки.

Который Вы могли сделать с жемчугом:

perl -0777 -pe 's/\n{2,}//gs' file

Вы могли также использовать perl's использования -i отметьте для редактирования файлов на месте.

perl -0777 -pi -e 's/\n{2,}//gs' file1 file2...
0
27.01.2020, 19:56

Существует еще более короткий способ удаления пустых строк в AWK:

awk 'NF' file

Но чтобы получить желаемый результат, достаточно всего лишь одной строчки:

awk 'NF {printf("%s ", $0); i++;} ! (i % 2) {printf("\n");}' file

Пояснение

В AWK пустая строка означает, что строка/запись не имеет полей, то есть переменная NF (Number of Fields) равна нулю. Приведенная выше строка будет выполнена только в том случае, если NF > 0, при этом будут напечатаны все строки, кроме пустых.

Счетчик i++ - это счетчик непустых строк.

Оператор !(i % 2) используется для печати двух последовательных непустых строк в соответствии с желаемым способом вывода, то есть каждый раз, когда находится кратное 2, оператор modulo !(i % 2) выдает 1, что завершает конкатенацию двух непустых строк.

0
27.01.2020, 19:56

Теги

Похожие вопросы