Supprimer des lignes dans un fichier texte qui contient une chaîne de caractères
Comment puis-je utiliser sed pour supprimer toutes les lignes dans un fichier texte qui contient une chaîne de caractères?
Vous devez vous connecter pour publier un commentaire.
À supprimer la ligne et de l'impression de la sortie standard:
Pour modifier directement le fichier ne fonctionne pas avec BSD sed:
Même, mais pour BSD sed (Mac OS X et FreeBSD) – ne fonctionne pas avec GNU sed:
Pour modifier directement le fichier (et de créer une copie de sauvegarde) – fonctionne avec les systèmes BSD et GNU sed:
sed '/pattern to match/d' ./infile > ./newfile
ou si vous voulez faire une édition sur place, alors vous pouvez ajouter la-i
drapeau de sed comme danssed -i '/pattern to match/d' ./infile
. Notez que le-i
indicateur nécessite GNU sed et n'est pas portablesed -i.backup '/pattern to match/d' ./infile
) Qui m'a dans l'ensemble avec en place des modifications.sed
pour les fichiers qui ne sont pas sous contrôle de version.sed -i '' '/pattern/d' ./infile
.-i 'bak'
ou-i.bak
sed
. Nous espérons que cette mise à jour une réponse commune pour les deux; il fonctionne certes avec GNUsed
4.2.2sed -i.bak "/str/d" ./infile
supprime la totalité de mon fichier.sed -i.bak "\#$pattern_variable_containing_slashes#d" ./infile
sed -i -e '/pattern/d' files..
. La raison supplémentaire param est besoin de ed est parce que-i
prendrait le modèle comme un param.sed '/pattern to match/d' ./infile > temp && mv temp infile
sed -i
mais PAS imprimer la sortie standard?-i
ne doit pas imprimer sur la sortie standard, par sa nature mêmegsed
avec MacPorts avecsudo port install gsed
.sed -i '\#cd /home$#d' myfile
Il existe de nombreuses autres manières de supprimer les lignes avec chaîne spécifique en plus de
sed
:AWK
Ruby (1.9+)
Perl
Shell (bash 3.2 et versions ultérieures)
GNU grep
Et bien sûr
sed
(l'impression de l'inverse est plus rapide que la suppression effective):sed
exemple, ont un comportement différent, il ne grep! il doit être quelque chose commesed -n -i '/pattern/!p' file
.grep -v "pattern" file > temp; mv temp file
Cela pourrait s'appliquer à d'autres exemples en fonction de la valeur de retour.seq -f %f 10000000 >foo.txt
. sed d:time sed -i '' '/6543210/d' foo.txt
réel 0m9.294s. sed !p:time sed -i '' -n '/6543210/!p' foo.txt
réel 0m13.671s. (Pour les petits fichiers, la différence est plus grande.)while IFS= read -r line
à la place (ce comportement n'a rien à voir avec OS/X, ce qui est normal dans tous les POSIX coquilles)Vous pouvez utiliser sed pour remplacer les lignes en place dans un fichier. Cependant, il semble être beaucoup plus lent que d'utiliser grep pour l'inverse dans le second fichier, puis en déplaçant le deuxième fichier de l'original.
par exemple
ou
La première commande prend 3 fois plus de temps sur ma machine de toute façon.
sed '/pattern/d' filename > filename2; mv filename2 filename
cat filename | grep -v "pattern" > filename
Le moyen facile de le faire, avec GNU
sed
:Vous pouvez envisager d'utiliser
ex
(qui est un standard d'Unix à base de commandes de l'éditeur):où:
+
exécute compte tenu de commande Ex (man ex
), de même que-c
qui exécutewq
(écrire et quitter)g/match/d
- Ex de commande à supprimer les lignes avec lematch
, voir: La puissance de gL'exemple ci-dessus est conforme à POSIX méthode pour l'édition d'un fichier de ce poste à Unix.SE et Spécifications POSIX pour
ex
.La différence avec
sed
est que:Sauf si vous aimez portables code, I/O frais généraux et à certains autres mauvais effets secondaires. Donc, fondamentalement, certains paramètres (tels que la place/
-i
) sont non-standard FreeBSD extensions et peuvent ne pas être disponibles sur d'autres systèmes d'exploitation.man ex
il me donne l'homme pourvim
, il sembleex
fait partie de vim... si j'ai compris tout cela signifie que le modèle de syntaxe pourmatch
est vimregex.com qui est similaire, mais différent de la norme POSIX et PCRE saveurs?:g
est POSIX commande avec certains les légères différences. Je suppose PCRE en a été tiré.J'ai eu du mal avec ce sur Mac. De Plus, j'avais besoin de le faire en utilisant des variables de remplacement.
J'ai donc utilisé:
sed -i '' "/$pattern/d" $file
où
$file
est le fichier où la suppression est nécessaire et$pattern
est le motif pour être assorti de la suppression.J'ai pris les
''
de cette commentaire.La chose à noter ici est l'utilisation de guillemets dans
"/$pattern/d"
. Variable ne fonctionne pas lorsque nous utilisons des guillemets simples.sed
nécessite un paramètre après-i
, donc si vous ne voulez pas d'une sauvegarde, vous devez toujours ajouter une chaîne vide:-i ''
sed -i "/$pattern/d" $file
. Je vous remercie pour votre réponse.J'ai fait un petit test avec un fichier qui contient environ 345 000 lignes. La manière avec
grep
semble être autour de 15 fois plus rapide que lased
méthode dans ce cas.J'ai essayé avec et sans la mise LC_ALL=C, il ne semble pas modifier les horaires de manière significative. La chaîne de recherche (CDGA_00004.pdbqt.gz.tar) est quelque part dans le milieu du fichier.
Voici les commandes et les horaires:
Pour obtenir une place comme résultat avec
grep
vous pouvez faire ceci:bash
shell ou similaires (pastcsh
).Vous pouvez également utiliser cette:
Ici
-v
pourrez imprimer autre que votre modèle (c'est à dire inverser la correspondance).SED:
'/James\|John/d'
-n '/James\|John/!p'
AWK:
'!/James|John/'
/James|John/{suivant;} {print}
GREP:
-v 'James\|John"
La première commande modifie le fichier(s) place (-i).
La deuxième commande fait la même chose, mais conserve une copie ou sauvegarde du fichier d'origine(s) par l'ajout d' .bk pour les noms de fichier (.bk peut être changé à n'importe quoi).
echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt
Juste au cas où quelqu'un veut le faire pour les correspondances exactes de chaînes de caractères, vous pouvez utiliser le
-w
drapeau grep - w pour l'ensemble. C'est, par exemple, si vous souhaitez supprimer les lignes qui ont le numéro 11, mais de maintenir les lignes avec le numéro 111:Elle travaille également avec la
-f
drapeau si vous souhaitez exclure plusieurs exacte des motifs à la fois. Si la "liste noire" est un fichier avec plusieurs modèles sur chaque ligne que vous voulez supprimer dans "fichier":-w, --word-regexp Select only those lines containing matches that form whole words.
vs-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.