Exclua todas as linhas que começam com um # de um arquivo

182

Todas as linhas com comentários em um arquivo começam com #. Como posso excluir todas as linhas (e somente aquelas) que começam com #? Outras linhas que contêm #, mas não no início da linha, devem ser ignoradas.

Vila
fonte
1
Ele precisa trabalhar com a convenção comum que #blah \<nl>blahconta como uma única "linha lógica" porque a barra invertida escapa à nova linha?
sarnold
@sarnold: além de makequais utilitários usam as 'linhas de emendas de barra invertida antes de terminar um comentário'? As conchas (bash e ksh testadas) não. C e C ++ lidam com emenda de nova linha antes de outro processamento de diretivas de pré-processador, mas são diretivas em vez de comentários.
precisa
@ Jonathan: Incrível. Eu tinha assumido que a \<nl>fuga comum também funcionaria nos comentários. Mas uau, eu estava errado. Ainda não consegui encontrar outro exemplo ... :) Obrigado!
sarnold

Respostas:

302

Isso pode ser feito com uma linha de comando sed :

sed '/^#/d'

Isso diz: "encontre todas as linhas que começam com # e exclua-as, deixando todo o resto".

Raymond Hettinger
fonte
9
versão mais curta:sed /^#/d
kev
80
Para linux noobs como eu: #sed '/^#/ d' < inputFile.txt > outputFile.txt
Neil McGuigan
50
Versão mais curta: sed -i '/^#/d' filepath.
Lesderid 11/10
14
E sed -i '' '/^#/d' filepathno Mac ( porque o sufixo -i é obrigatória )
paulcm
1
@Viesturs Tente isto: # awk '/^#/ && !first { first=1 ; next } { print $0}'
Raymond Hettinger
56

Estou um pouco surpreso que ninguém tenha sugerido a solução mais óbvia:

grep -v '^#' filename

Isso resolve o problema como indicado.

Mas observe que uma convenção comum é que tudo, de um #até o final de uma linha, seja tratado como um comentário:

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

embora isso trate, por exemplo, um #caractere dentro de uma string literal como o início de um comentário (que pode ou não ser relevante para o seu caso) (e deixa linhas vazias).

Uma linha começando com um espaço em branco arbitrário seguido por #também pode ser tratada como um comentário:

grep -v '^ *#' filename

se espaço em branco for apenas espaços, ou

grep -v '^[  ]#' filename

onde os dois espaços são na verdade um espaço seguido por um caractere de tabulação literal (digite "control-v tab").

Para todos esses comandos, omita o filenameargumento para ler da entrada padrão (por exemplo, como parte de um canal).

Keith Thompson
fonte
Eu adicionei uma nova resposta que se baseia nessa resposta.
Acumenus 30/10
Eu tive problemas usando o grep dessa maneira no Windows. A solução é substituir 'por ", por exemplogrep -v "^#" filename
Serg
14

O oposto da solução de Raymond:

sed -n '/^#/!p'

"não imprima nada, exceto linhas que NÃO começam com #"

ata
fonte
9

você pode editar diretamente seu arquivo com

sed -i '/^#/ d'

Se você também deseja excluir linhas de comentário que começam com algum espaço em branco, use

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

Normalmente, você deseja manter a primeira linha do seu script, se for um sha-bang, portanto sed, não exclua as linhas começando com #!. também deve excluir linhas, que contêm apenas um hash, mas nenhum texto. junte tudo:

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

Para estar em conformidade com todas as variantes sed, você precisa adicionar uma extensão de backup à -iopção:

sed -i.bak '/^\s*#/ d' $file
rm -Rf $file.bak
rubo77
fonte
1
mais um para o qual um espaço
pawar deepaksingh
7

Você pode usar o seguinte para uma solução awk -

awk '/^#/ {sub(/#.*/,"");getline;}1' inputfile
jaypal singh
fonte
5

Esta resposta baseia-se na resposta anterior de Keith .

egrep -v "^[[:blank:]]*#" deve filtrar as linhas de comentário.

egrep -v "^[[:blank:]]*(#|$)" deve filtrar os comentários e as linhas vazias, como é frequentemente útil.

Para obter informações sobre [:blank:]e outras classes de caracteres, consulte https://en.wikipedia.org/wiki/Regular_expression#Character_classes .

Acumenus
fonte
Supondo que você egrepsuporte essa sintaxe; versões mais antigas podem não.
Keith Thompson
-3

Aqui está um loop para todos os arquivos com alguma extensão:

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
Bruno Damas
fonte