Удалить все строки, начинающиеся с # из файла

182

Все строки с комментариями в файле начинаются с #. Как я могу удалить все строки (и только те строки), которые начинаются с #? Другие строки, содержащие #, но не в начале строки, следует игнорировать.

Деревня
источник
1
Должен ли он работать с общим соглашением, которое #blah \<nl>blahсчитается одной «логической строкой», потому что обратный слеш экранирует символ новой строки?
Сарнольд
@sarnold: кроме того make, какие утилиты используют «линии сращивания с обратной косой чертой перед завершением комментария»? Снаряды (протестированные bash и ksh) этого не делают. C и C ++ обрабатывают сплайны новой строки перед другой обработкой директив препроцессора, но они являются директивами, а не комментариями.
Джонатан Леффлер
@ Джонатан: Отлично. Я предполагал, что общее \<nl>побег также будет работать с комментариями. Но вау, я был неправ. Я еще не смог найти другой пример ... :) Спасибо!
Сарнольд

Ответы:

302

Это можно сделать с помощью однострочной команды sed :

sed '/^#/d'

Это говорит: «найдите все строки, начинающиеся с #, и удалите их, оставив все остальное».

Раймонд Хеттингер
источник
9
укороченная версия:sed /^#/d
kev
80
Для Linux Noobs, как я:sed '/^#/ d' < inputFile.txt > outputFile.txt
Нил Макгиган
50
Кратчайшая версия sed -i '/^#/d' filepath.
Lesderid
14
И sed -i '' '/^#/d' filepathна Mac ( потому что суффикс -i является обязательным )
paulcm
1
@Viesturs Попробуйте это: awk '/^#/ && !first { first=1 ; next } { print $0}'
Раймонд Хеттингер
56

Я немного удивлен, что никто не предложил наиболее очевидное решение:

grep -v '^#' filename

Это решает проблему, как указано.

Но обратите внимание, что общее соглашение для всего, от #конца до конца, должно рассматриваться как комментарий:

sed 's/#.*$//' filename

хотя это обрабатывает, например, #символ внутри строкового литерала как начало комментария (что может или не может иметь значение для вашего случая) (и оставляет пустые строки).

Строка, начинающаяся с произвольного пробела, за которой #может следовать, также может рассматриваться как комментарий:

grep -v '^ *#' filename

если пробел только пробелы, или

grep -v '^[  ]#' filename

где два пробела фактически являются пробелом, за которым следует буквальный символ табуляции (введите «control-v tab»).

Для всех этих команд опустите filenameаргумент для чтения из стандартного ввода (например, как часть канала).

Кит Томпсон
источник
Я добавил новый ответ, который основан на этом ответе.
Acumenus
У меня были проблемы с использованием grep таким способом в Windows. Решение состоит в том, чтобы заменить «на», например,grep -v "^#" filename
Serg
14

Противоположность решения Раймонда:

sed -n '/^#/!p'

"не печатайте ничего, кроме строк, которые НЕ начинаются с #"

ата
источник
9

Вы можете напрямую редактировать свой файл с

sed -i '/^#/ d'

Если вы также хотите удалить строки комментариев, начинающиеся с пробелов, используйте

sed -i '/^\s*#/ d'

Обычно вы хотите сохранить первую строку вашего скрипта, если это sha-bang, поэтому sedне следует удалять строки, начинающиеся с #!. также следует удалить строки, которые содержат только хэш, но не содержат текста. поставить все это вместе:

sed -i '/^\s*\(#[^!].*\|#$\)/d'

Чтобы соответствовать всем вариантам sed, вам необходимо добавить расширение резервной копии к -iопции:

sed -i.bak '/^\s*#/ d' $file
rm -Rf $file.bak
rubo77
источник
1
плюс 1 за то, что пространство
Дипаксингх Павар
7

Для решения awk вы можете использовать следующее:

awk '/^#/ {sub(/#.*/,"");getline;}1' inputfile
Джайпал Сингх
источник
5

Этот ответ основан на более раннем ответе Кейта .

egrep -v "^[[:blank:]]*#" следует отфильтровать строки комментариев.

egrep -v "^[[:blank:]]*(#|$)" следует отфильтровать как комментарии, так и пустые строки, что часто бывает полезно.

Для получения информации о [:blank:]других классах символов см. Https://en.wikipedia.org/wiki/Regular_expression#Character_classes .

Акаменус
источник
Предполагая, что вы egrepподдерживаете этот синтаксис; старые версии не могут.
Кит Томпсон
-3

Вот это с циклом для всех файлов с некоторым расширением:

ll -ltr *.filename_extension > list.lst

for i in $(cat list.lst | awk '{ print $8 }') # validate if it is the 8 column on ls 
do
    echo $i
    sed -i '/^#/d' $i
done
Бруно Дамас
источник