Видаліть порожні рядки за допомогою sed


351

Я намагаюся видалити порожні рядки за допомогою sed:

sed '/^$/d'

але мені не пощастило з цим.

Наприклад, у мене є такі рядки:

xxxxxx


yyyyyy


zzzzzz

і я хочу, щоб це було так:

xxxxxx
yyyyyy
zzzzzz

Яким має бути код для цього?


2
ваша команда sed виглядає чудово, вона повинна спрацювати
перреально

Наведена вище команда не працює, навіть якщо у вас немає пробілу / вкладки, але закінчення рядків CR + LF .
devnull

Відповіді:


628

У вашому "порожньому" рядку можуть бути пробіли чи вкладки. Використання POSIX класів з , sedщоб видалити всі рядки , що містять тільки пропуски:

sed '/^[[:space:]]*$/d'

Більш коротка версія, яка використовує ERE, наприклад, з gnu sed:

sed -r '/^\s*$/d'

(Зверніть увагу , що СЕД дійсно НЕ підтримує PCRE.)


3
@HuStmpHrrr gnu sed взагалі не підтримує PCRE. це ERE з-r
Кент,

8
OS X потрібно sed -i "" '/^[[:space:]]*$/d' <filename>,
jww

@BernieReiter ^\s*$відповідатиме всім "порожнім" рядкам, порожній тут означає, що рядок не містить символів, або рядок містить лише порожні рядки (наприклад, пробіли). Усі відповідні рядки будуть видалені sed, dкомандою.
Кент

97

Я пропускаю awkрішення:

awk 'NF' file

Що поверне:

xxxxxx
yyyyyy
zzzzzz

Як це працює? Оскільки NFозначає "кількість полів", у цих рядках, що є порожніми, є 0 фієлів, так що awk оцінює 0 до False, і жоден рядок не друкується; однак, якщо є щонайменше одне поле, оцінка True і змушує awkвиконувати свою дію за замовчуванням: надрукуйте поточний рядок.


1
Ох. Навіть працює з "мінімізованою" версією BKD BSD (версія 20121220 (FreeBSD). Дякую :-)
Берні Рейтер,

@BernieReiter ласкаво просимо :) Так, це дуже проста ідіоматична річ, яку дозволяють усі версії awk.
fedorqui 'ТАК перестаньте шкодити'

І це набагато швидше, хоча - для швидкого і брудного випробування - я двічі посилаюся на awk: $ time (topic companies <data.tpx | awk 'NF' - | awk -f dialog_menu.awk -) real 0m0.006s user 0m0.000s sys 0m0.008s $ time (topic companies <data.tpx | gsed '/^\s*$/d' | awk -f dialog_menu.awk -) real 0m0.014s user 0m0.002s sys 0m0.006s Чи знаєте ви про прекрасний спосіб включити це до сценарію awk, наприклад, у шаблон? awk '/ mypattern / {do stuff ...}'
Берні Рейтер

@BernieReiter можна сказати awk 'NF {do stuff...}'.
fedorqui 'ТАК перестаньте шкодити'

1
Зауважте, що це також буде ігнорувати рядки лише з пробілом.
wisbucky

60

sed '/^$/d'має бути добре, чи очікуєте ви змінити файл на місці? Якщо так, ви повинні використовувати -iпрапор.

Можливо, ці рядки не порожні, тому, якщо це так, подивіться на це питання Видаліть порожні рядки з txtfiles, видаліть пробіли від початку та кінця рядка. Я вважаю, що саме цього ви намагаєтеся досягти.


так. я змінюю файл. * .csv як слід ставити -i до команди sed?
jonas

2
sed -i '/^$/d'це один із способів зробити це.
Альберто Закканні

49

1
Вони відображаються правильно у вашому інтернет-інструменті, але []їх не слід уникати в дужковому виразі, тому код тут неправильний для \[\[:space:\]\]або \[ \t\]- повинен бути [[:space:]]і [ \t].
Бенджамін В.

1
@BenjaminW. Дякуємо, що це зробили. Вони не від оригіналу автора, але прийшли з редагування 3, коли він був змінений із звичайного тексту на "код", який потім "викрив" втечу `` \. Я зараз їх виправив.
wisbucky

30

Я вважаю, що це найпростіший і найшвидший:

cat file.txt | grep .

Якщо вам також потрібно ігнорувати всі пробіли, спробуйте:

cat file.txt | grep '\S'

Приклад:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

виходи

7
5

5
Немає необхідності cat, також grepбере файли:grep . file.txt
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

3
Так, я знаю, але в початковому питанні не згадувалося, чи джерело - це файл чи щось інше, тому рішення - це те, що приходить після "|", а перед ним лише приклад джерела. Просто відрізнити рішення від джерела рядків.
Вадим

2
grep '\S'точно не є портативним. Якщо у вас є, grep -Pто ви можете використовувати, grep -P '\S'але це не підтримується на всіх платформах.
трійчатка

Недоліком grep .порівняно з іншими рішеннями є те, що воно виділить увесь текст червоним кольором. Інші рішення дозволяють зберегти оригінальні кольори. Порівняйте unbuffer apt search foo | grep .зunbuffer apt search foo | grep -v ^$
wisbucky

15

За допомогою прийнятої тут відповіді та прийнятої відповіді вище, я використав:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

Це охоплює всі основи і прекрасно працює для моїх потреб. Кудос до оригінальних плакатів @Kent та @kev


5

Ви можете сказати:

sed -n '/ / p' filename    #there is a space between '//'

.. що означає print all lines except the empty one(s)і будь тихо
Тимо


2

Ви можете зробити щось подібне, використовуючи і "grep":

egrep -v "^$" file.txt


2

Ви, швидше за все, бачите несподівану поведінку, оскільки ваш текстовий файл створений у Windows, тому послідовність завершення рядка є \r\n. Ви можете використовувати dos2unix для перетворення його в текстовий файл стилю UNIX перед запуском sed або використання

sed -r "/^\r?$/d"

щоб видалити порожні рядки, незалежно від того, є або повернення вагона.


Привіт, що це за -rпрапор і чи можна комбінувати його з тим, -iщоб безпосередньо змінювати файл та уникати друку на екран. Крім того, я думаю, що ця команда також sed -r "/^\r$/d"
діятиме

0

Моя bashспецифічна відповідь полягає в тому, щоб рекомендувати для цього використовувати perlоператор підстановки з глобальним gпрапором шаблону :

$ perl -pe s'/^\n|^[\ ]*\n//g' $file
xxxxxx
yyyyyy
zzzzzz

Ця відповідь ілюструє облік того, чи є порожні рядки в них пробіли ( [\ ]*), а також використання |для розділення кількох пошукових термінів / полів. Тестували на macOS High Sierra та CentOS 6/7.

FYI, оригінальний код OP sed '/^$/d' $fileпрацює чудово в bashTerminal на macOS High Sierra та CentOS 6/7 Linux на високопродуктивних кластерах суперкомп'ютерів.


-3

Для мене з FreeBSD 10.1 з sed працював тільки це рішення:

sed -e '/^[     ]*$/d' "testfile"

всередині []знаки пробілу та вкладки.

тестовий файл містить:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.