Usuń wszystkie linie zaczynające się od # z pliku

182

Wszystkie wiersze z komentarzami w pliku zaczynają się od #. Jak mogę usunąć wszystkie linie (i tylko te linie), które zaczynają się od #? Inne wiersze zawierające #, ale nie na początku wiersza, należy zignorować.

Wioska
źródło
1
Czy musi współpracować ze wspólną konwencją, która #blah \<nl>blahliczy się jako pojedyncza „linia logiczna”, ponieważ odwrotny ukośnik ucieka przed nową linią?
sarnold 21.11.11
@sarnold: oprócz tego make, które narzędzia używają „linii odwrotnego ukośnika przed zakończeniem komentarza”? Powłoki (testowane na bash i ksh) nie. C i C ++ obsługują splicing nowego wiersza przed innym przetwarzaniem dyrektyw preprocesora, ale są to dyrektywy, a nie komentarze.
Jonathan Leffler
@Jathanathan: Awesome. Założyłem, że wspólne \<nl>ucieczkowanie zadziała również na komentarze. Ale łał, myliłem się. Nie znalazłem jeszcze innego przykładu ... :) Dzięki!
sarnold 21.11.11

Odpowiedzi:

301

Można to zrobić za pomocą sed-one-liner :

sed '/^#/d'

To mówi: „znajdź wszystkie wiersze zaczynające się od # i usuń je, pozostawiając wszystko inne”.

Raymond Hettinger
źródło
9
krótsza wersja:sed /^#/d
kev
80
Dla linuksowych noobów takich jak ja:sed '/^#/ d' < inputFile.txt > outputFile.txt
Neil McGuigan
49
Najkrótsza wersja: sed -i '/^#/d' filepath.
lesderid
14
A sed -i '' '/^#/d' filepathna Macu ( ponieważ sufiks -i jest obowiązkowy )
paulcm
1
@Viesturs Spróbuj tego: awk '/^#/ && !first { first=1 ; next } { print $0}'
Raymond Hettinger,
56

Jestem trochę zaskoczony, że nikt nie zaproponował najbardziej oczywistego rozwiązania:

grep -v '^#' filename

To rozwiązuje problem, jak stwierdzono.

Zauważ jednak, że wspólna konwencja #traktuje wszystko od końca do końca linii jako komentarz:

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

chociaż traktuje to na przykład #znak w dosłownym ciągu jako początek komentarza (który może, ale nie musi mieć znaczenia w twoim przypadku) (i pozostawia puste wiersze).

Linia zaczynająca się od dowolnej spacji, po której następuje, #może być również traktowana jako komentarz:

grep -v '^ *#' filename

jeśli białe znaki to tylko spacje, lub

grep -v '^[  ]#' filename

gdzie te dwie spacje są w rzeczywistości spacją, po której następuje dosłowny znak tabulacji (wpisz „control-v tab”).

W przypadku wszystkich tych poleceń pomiń filenameargument do odczytu ze standardowego wejścia (np. Jako część potoku).

Keith Thompson
źródło
Dodałem nową odpowiedź, która opiera się na tej odpowiedzi.
Acumenus
Miałem problemy z używaniem grep w ten sposób w systemie Windows. Rozwiązaniem jest zastąpienie słowa „przez”, np.grep -v "^#" filename
Serg
14

Przeciwieństwo rozwiązania Raymonda:

sed -n '/^#/!p'

„nie drukuj niczego, z wyjątkiem linii, które NIE zaczynają się od #”

ata
źródło
9

możesz bezpośrednio edytować swój plik za pomocą

sed -i '/^#/ d'

Jeśli chcesz również usunąć wiersze komentarza, które zaczynają się od pewnego spacji, użyj

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

Zwykle chcesz zachować pierwszą linię skryptu, jeśli jest to sha-bang, więc sednie należy usuwać linii zaczynających się od #!. powinien także usuwać wiersze, które zawierają tylko skrót, ale nie zawierają tekstu. poskładać wszystko do kupy:

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

Aby zachować zgodność ze wszystkimi wariantami sed, musisz dodać kopię zapasową rozszerzenia do -iopcji:

sed -i.bak '/^\s*#/ d' $file
rm -Rf $file.bak
rubo77
źródło
1
plus 1 za ten, który spacja
deepaksingh pawar
7

Możesz użyć następujących rozwiązań dla rozwiązania awk -

awk '/^#/ {sub(/#.*/,"");getline;}1' inputfile
jaypal singh
źródło
5

Ta odpowiedź opiera się na wcześniejszej odpowiedzi Keitha .

egrep -v "^[[:blank:]]*#" powinien odfiltrować wiersze komentarza.

egrep -v "^[[:blank:]]*(#|$)" powinien odfiltrować zarówno komentarze, jak i puste wiersze, co jest często przydatne.

Informacje o [:blank:]klasach znaków i innych klasach można znaleźć na stronie https://en.wikipedia.org/wiki/Regular_expression#Character_classes .

Acumenus
źródło
Zakładając, że egrepobsługuje tę składnię; starsze wersje mogą nie.
Keith Thompson
-3

Oto pętla dla wszystkich plików z pewnym rozszerzeniem:

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
źródło