Fondamentalement, je veux prendre comme texte d'entrée d'un fichier, supprimer une ligne de ce fichier et renvoyer la sortie dans le même fichier. Quelque chose dans ce sens si cela rend les choses plus claires.
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > file_name
cependant, lorsque je fais cela, je me retrouve avec un fichier vierge. Des pensées?
Réponses:
Vous ne pouvez pas faire cela car bash traite d'abord les redirections, puis exécute la commande. Ainsi, au moment où grep regarde nom_fichier, il est déjà vide. Vous pouvez cependant utiliser un fichier temporaire.
comme ça, pensez à utiliser
mktemp
pour créer le tmpfile mais notez que ce n'est pas POSIX.la source
>
redirection ouvrira le fichier et le tronquera avant le lancement du shellgrep
.sponge
commande doit être acceptée.Utilisez une éponge pour ce genre de tâches. Sa partie de moreutils.
Essayez cette commande:
la source
brew install moreutils
.sudo apt-get install moreutils
sur les systèmes basés sur Debian.Utilisez plutôt sed:
la source
-i
est uniquement une extension GNU, notez simplement.-i ''
que l'extension n'est pas strictement obligatoire, mais l'-i
option nécessite un argument.essayez ce simple
Votre fichier ne sera pas vierge cette fois :) et votre sortie est également imprimée sur votre terminal.
la source
/dev/null
ou vers des endroits similaires.Vous ne pouvez pas utiliser l'opérateur de redirection (
>
ou>>
) vers le même fichier, car il a une priorité plus élevée et il créera / tronquera le fichier avant même que la commande ne soit appelée. Pour éviter cela, vous devez utiliser des outils appropriés tels quetee
,sponge
,sed -i
ou tout autre outil qui peut écrire des résultats dans le fichier (par exemplesort file -o file
).Fondamentalement, rediriger l'entrée vers le même fichier d'origine n'a pas de sens et vous devez utiliser des éditeurs sur place appropriés pour cela, par exemple l'éditeur Ex (qui fait partie de Vim):
où:
'+cmd'
/-c
- exécuter n'importe quelle commande Ex / Vimg/pattern/d
- Retirer les lignes correspondant à un motif à l' aide global (help :g
)-s
- mode silencieux (man ex
)-c wq
- exécuter:write
et:quit
commandesVous pouvez utiliser
sed
pour obtenir le même (comme cela a déjà montré dans d' autres réponses), mais en place (-i
) est non-standard extension de FreeBSD (peut fonctionner différemment entre Unix / Linux) et , fondamentalement , il est un s tream ed Itor, pas un éditeur de fichiers . Voir: Le mode Ex a-t-il une utilisation pratique?la source
Une alternative de ligne - définissez le contenu du fichier comme variable:
la source
Étant donné que cette question est le meilleur résultat dans les moteurs de recherche, voici une ligne unique basée sur https://serverfault.com/a/547331 qui utilise un sous-shell au lieu de
sponge
(qui ne fait souvent pas partie d'une installation vanille comme OS X) :Le cas général est:
Edit, la solution ci-dessus a quelques mises en garde:
printf '%s' <string>
doit être utilisé à la place deecho <string>
pour que les fichiers contenant-n
ne provoquent pas de comportement indésirable.x
à la sortie et le supprimer à l'extérieur via l' expansion des paramètres d'une variable temporaire comme${v%x}
.$v
stomps la valeur de toute variable existante$v
dans l'environnement shell actuel, nous devons donc imbriquer l'expression entière entre parenthèses pour conserver la valeur précédente.null
de la sortie. J'ai vérifié cela en appelantdd if=/dev/zero bs=1 count=1 >> file_name
et en le visualisant en hexadécimal aveccat file_name | xxd -p
. Maisecho $(cat file_name) | xxd -p
est dépouillé. Donc, cette réponse ne doit pas être utilisée sur des fichiers binaires ou quoi que ce soit utilisant des caractères non imprimables, comme l'a souligné Lynch .La solution générale (albiet légèrement plus lente, plus gourmande en mémoire et en supprimant toujours les caractères non imprimables) est:
Test de https://askubuntu.com/a/752451 :
Devrait imprimer:
Alors que l'appel
cat file_uniquely_named.txt > file_uniquely_named.txt
dans le shell actuel:Imprime une chaîne vide.
Je n'ai pas testé cela sur de gros fichiers (probablement plus de 2 ou 4 Go).
J'ai emprunté cette réponse à Hart Simha et kos .
la source
cat
et le place comme premier argument dansecho
. Bien sûr, les variables non imprimables ne sortiront pas correctement et corrompront les données. N'essayez pas de rediriger un fichier vers lui-même, cela ne peut tout simplement pas être bon.Il y a aussi
ed
(comme alternative àsed -i
):la source
Vous pouvez le faire en utilisant la substitution de processus .
C'est un peu un hack car bash ouvre tous les tuyaux de manière asynchrone et nous devons contourner cela en utilisant
sleep
donc YMMV.Dans votre exemple:
>(sleep 1 && cat > file_name)
crée un fichier temporaire qui reçoit la sortie de grepsleep 1
retards pendant une seconde pour donner à grep le temps d'analyser le fichier d'entréecat > file_name
écrit enfin la sortiela source
Vous pouvez utiliser slurp avec POSIX Awk:
Exemple
la source
C'est très possible, il vous suffit de vous assurer qu'au moment où vous écrivez la sortie, vous l'écrivez dans un fichier différent. Cela peut être fait en supprimant le fichier après avoir ouvert un descripteur de fichier, mais avant d'y écrire:
Ou ligne par ligne, pour mieux le comprendre:
C'est toujours une chose risquée à faire, car si COMMAND ne fonctionne pas correctement, vous perdrez le contenu du fichier. Cela peut être atténué en restaurant le fichier si COMMAND renvoie un code de sortie différent de zéro:
Nous pouvons également définir une fonction shell pour faciliter son utilisation:
Exemple :
Notez également que cela conservera une copie complète du fichier d'origine (jusqu'à ce que le troisième descripteur de fichier soit fermé). Si vous utilisez Linux et que le fichier que vous traitez est trop volumineux pour tenir deux fois sur le disque, vous pouvez consulter ce script qui dirigera le fichier vers la commande spécifiée bloc par bloc tout en annulant le déjà traité blocs. Comme toujours, lisez les avertissements dans la page d'utilisation.
la source
Essaye ça
la source
Ce qui suit accomplira la même chose que
sponge
, sans exigermoreutils
:La
--random-source=/dev/zero
partie astucesshuf
pour faire son travail sans faire de mélange du tout, donc elle mettra en mémoire tampon votre entrée sans la modifier.Cependant, il est vrai que l'utilisation d'un fichier temporaire est préférable, pour des raisons de performances. Alors, voici une fonction que j'ai écrite qui le fera pour vous de manière généralisée:
la source
J'utilise généralement le programme tee pour faire ceci:
Il crée et supprime un fichier temporaire par lui-même.
la source
tee
n'est pas garanti de fonctionner. Voir askubuntu.com/a/752451/335781 .