web-dev-qa-db-fra.com

Comment supprimer tous les commentaires d'un fichier?

J'ai un dossier avec des commentaires:

foo
bar
stuff
#Do not show this...
morestuff
evenmorestuff#Or this

Je veux juste imprimer tout le code non commenté:

foo
bar
stuff
morestuff
evenmorestuff

Pouvoir retirer des commentaires d'un fichier est si important ... Quelle est la bonne façon de le faire?

25
Questionmark

Une façon de supprimer tous les commentaires consiste à utiliser grep avec -o option:

grep -o '^[^#]*' file

  • -o: imprime uniquement les correspondances partie de la ligne
  • première ^: début de la ligne
  • [^#]*: tout caractère sauf # répété zéro ou plusieurs fois

Notez que les lignes vides seront également supprimées, mais les lignes avec uniquement des espaces resteront.

42
jimmij

Je crois que sed peut faire un bien meilleur travail que grep. Quelque chose comme ça:

sed '/^[[:blank:]]*#/d;s/#.*//' your_file

Explication

  • sed regardera par défaut votre fichier ligne par ligne et imprimera chaque ligne après avoir éventuellement appliqué les transformations dans les guillemets. (sed '' your_file affichera simplement toutes les lignes inchangées).
  • Ici, nous donnons à sed deux commandes à exécuter sur chaque ligne (elles sont séparées par un point-virgule).
  • La première commande dit: /^[[:blank:]]*#/d. En anglais, cela signifie que si la ligne correspond à un hachage à son début (précédé d'un nombre quelconque de blancs de début), supprimez cette ligne (elle ne sera pas imprimée).
  • La deuxième commande est: s/#.*//. En anglais c'est-à-dire, remplacez par une marque de hachage suivie par autant de choses que vous pouvez trouver (jusqu'à la fin de la ligne, c'est-à-dire) avec rien (rien n'est l'espace vide entre les deux derniers //).
  • En résumé, cela passera par votre fichier en supprimant les lignes qui se composent entièrement de commentaires et toutes les lignes restantes après cela auront les commentaires supprimés.
32
Joseph R.

Comme d'autres l'ont souligné, sed et d'autres outils basés sur du texte ne fonctionneront pas bien si des parties d'un script ressemblent à des commentaires mais ne le sont pas. Par exemple, vous pourriez trouver un # à l'intérieur d'une chaîne ou le $# et ${#param}.

J'ai écrit un formateur Shell appelé shfmt , qui a une fonctionnalité pour réduire le code. Cela comprend la suppression des commentaires, entre autres:

$ cat foo.sh
echo $# # inline comment
# lone comment
echo '# this is not a comment'
[mvdan@carbon:12] [0] [/home/mvdan]
$ shfmt -mn foo.sh
echo $#
echo '# this is not a comment'

L'analyseur et l'imprimante sont des packages Go, donc si vous souhaitez une solution personnalisée, il devrait être assez facile d'écrire un programme Go de 20 lignes pour supprimer les commentaires exactement comme vous le souhaitez.

4
Daniel

Vous pouvez obtenir la sortie requise à l'aide de la commande sed. La commande ci-dessous avait fait l'affaire pour moi.

sed 's/#.*$//g' FileName

  • #.*$ - Regexp filtrera toute la chaîne commençant par # jusqu'à la fin de la ligne

Ici, nous devons supprimer ces lignes afin que nous les remplacions par des pièces vides afin de sauter le remplacement.

  • g - mentionnant la recherche répétée du modèle jusqu'à la fin du fichier.

Syntaxe générale de sed: s/regexp/replacement/flags FileName

4
Sridhar DD

Cela a fonctionné pour moi

sed -i.old -E  "/^(#.*)$/d" file 
1
David Okwii

Suite à la 2ème réponse de Joseph R., j'ajoute /^$/d pour supprimer la ligne vierge.

sed '/^[[:blank:]]*#/d;s/#.*//;/^$/d'
1
Pierre-Damien

Exemple d'entrée

cat example.sh
#!/bin/bash
# example script

echo "# test";# echo "# test"

# check the first parameter
if [ "$1" = "#" ]; then 
  # test couple of different cases
  echo "#"; # output # character 
  echo '\#'; # output # character '#' for test purpose
  echo \#\#\#; # comment # comment # comment '# comment'
  echo \#
  echo \#;
  echo \#; # comment
fi
# end of the script

Supprimer les commentaires

sed -e '1{/^#!/ {p}}; /^[\t\ ]*#/d;/\.*#.*/ {/[\x22\x27].*#.*[\x22\x27]/ !{:regular_loop s/\(.*\)*[^\]#.*/\1/;t regular_loop}; /[\x22\x27].*#.*[\x22\x27]/ {:special_loop s/\([\x22\x27].*#.*[^\x22\x27]\)#.*/\1/;t special_loop}; /\\#/ {:second_special_loop s/\(.*\\#.*[^\]\)#.*/\1/;t second_special_loop}}' example.sh

Résultat

cat example.sh
#!/bin/bash

echo "# test";

if [ "$1" = "#" ]; then 
  echo "#"; 
  echo '\#'; 
  echo \#\#\#; 
  echo \#
  echo \#;
  echo \#;
fi

Lisez comment cela fonctionne à la source: https://blog.sleeplessbeastie.eu/2012/11/07/how-to-remove-comments-from-a-Shell-script/

1
Eduardo Cuomo

J'aime la réponse de Joseph mais j'en avais besoin pour me déshabiller // commentaires aussi donc je l'ai légèrement modifiée et testée sur redhat

# no comments alias
alias nocom="sed -E '/^[[:blank:]]*(\/\/|#)/d;s/#.*//' | strings"

# example
cat SomeFile | nocom | less

Je parie qu'il y a une meilleure façon de supprimer les lignes vides que d'utiliser des chaînes, mais c'était la solution rapide et sale que j'ai utilisée.

-à votre santé

1
brandon

La meilleure solution serait d'utiliser la commande:

sed -i.$(date +%F) '/^#/d;/^$/d' ntp.conf

Le -i est la modification sur place mais le préfixe suivant directement indique à sed de créer une sauvegarde. Dans ce cas avec une extension de date (ntp.conf.date) Nous exécutons deux commandes chacune avec un espace d'adressage, la première supprime les lignes commentées et la seconde, séparée de la première par un point-virgule, supprime les lignes vides.

J'ai trouvé cette solution sur: theurbanpenguin.com

1
jyoti

Vous pouvez utiliser une correspondance inversée comme ceci:

    #grep -v "#" filename

-v, --invert-match Inverse le sens de la correspondance, pour sélectionner les lignes non correspondantes. (-v est spécifié par POSIX.)

1
Raza
cat YOUR_FILE | cut -d'#' -f1

Il utilise # comme séparateur de colonnes et ne conserve que la première colonne (c'est tout avant #).

1
Alexey

Je poste ce qui fonctionne pour moi et semble avoir le plus de sens, après avoir lu les autres, avec explication. Quelques articles sont venus près, mais je ne pouvais pas encore commenter (parce que je suis un nouveau):

grep -E -v "(^#.*|^$)" filename
  • -E = Interpréter le modèle suivant comme une expression régulière, similaire à l'utilisation d'egrep
  • -v = Imprime l'inversion du motif (les lignes qui ne correspondent pas à l'expression seront imprimées)
  • "(^#.*|^$)" = ceci a un tube qui désigne une instruction OR. Cette expression indique d'imprimer toute ligne commençant par un # (et toute autre chose après) ) OR toute ligne avec zéro caractère entre le début et la fin de la ligne.

Le -v Imprimera à l'écran l'inversion de celui-ci, qui sera n'importe quelle ligne avec des caractères qui ne commence pas par un #.

0
jackbmg

Aucune des autres réponses ne semble rendre cette justice, soit elles laissent des lignes vides, soit des lignes où le commentaire n'est pas au premier caractère. J'ai fini par utiliser ceci:

cat << EOF >> ~/.bashrc
alias nocom='sed -e "/^\s*#/d" -e "/^\s*$/d"'
EOF

Cela crée un alias, afin que vous n'ayez pas à le mémoriser (ce qui est impossible au départ). Ouvrez une nouvelle session et vous aurez la nouvelle commande nocom. Ensuite, vous pouvez simplement

nocom /etc/foobar.conf

À votre santé.

0
bviktor

Utilisez une expression comme

egrep -v "#|$^" <file-name> 

: -v: fera une correspondance inversée

: #: correspondra à toutes les lignes commençant par #

: $ ^: correspondra à toutes les lignes vides

0
aditya