J'essaie de savoir s'il est possible de modifier un fichier dans une seule commande sed sans diffuser manuellement le contenu modifié dans un nouveau fichier, puis renommer le nouveau fichier en son nom d'origine. J'ai essayé l' -i
option mais mon système Solaris a dit que -i
c'était une option illégale. Existe-t-il une manière différente?
300
-i
est une option dans gnu sed, mais n'est pas dans sed standard. Cependant, il diffuse le contenu dans un nouveau fichier, puis renomme le fichier afin qu'il ne soit pas ce que vous voulez.Réponses:
L'
-i
option diffuse le contenu modifié dans un nouveau fichier, puis le renomme en arrière-plan, de toute façon.Exemple:
et
sur macOS .
la source
sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
Sur un système où
sed
n'a pas la possibilité de modifier les fichiers en place, je pense que la meilleure solution serait d'utiliserperl
:Bien que cela crée un fichier temporaire, il remplace l'original car un suffixe / extension vide sur place a été fourni.
la source
sudo
. Dans mon esprit, la question est de savoir comment éviter de créer et de renommer manuellement un fichier temporaire sans avoir à installer le dernier GNU ou BSDsed
. Utilisez simplement Perl.sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt
. Le fait que l'édition sur place effectue le changement de nom à l'aide d'un fichier temporaire ne signifie pas qu'il doit effectuer un changement de nom manuel lorsque l'option n'est pas disponible. Il existe d'autres outils qui peuvent faire ce qu'il veut, et Perl est le choix évident. Comment n'est-ce pas une réponse à la question d'origine?sed
. La question était en fait un très bon, mais il Apprécions a été diminuée par des gens qui soit ne peuvent pas lire les pages de manuel ou ne peut pas être pris la peine de réellement des questions lues ici sur le SO.Notez que sur OS X, vous pouvez obtenir des erreurs étranges comme "code de commande invalide" ou d'autres erreurs étranges lors de l'exécution de cette commande. Pour résoudre ce problème, essayez
En effet, sur la version OSX de
sed
, l'-i
option attend unextension
argument, de sorte que votre commande est en fait analysée commeextension
argument et que le chemin d'accès au fichier est interprété comme le code de commande. Source: https://stackoverflow.com/a/19457213la source
brew install gnu-sed
avec unPATH
vous permettra d'utiliser la version GNU de sed. Merci d'avoir mentionné; un gratte-tête précis.Ce qui suit fonctionne bien sur mon mac
Nous remplaçons foo par bar dans le fichier d'exemple. La sauvegarde du fichier d'origine sera enregistrée dans sample.bak
Pour modifier en ligne sans sauvegarde, utilisez la commande suivante
la source
Une chose à noter,
sed
ne peut pas écrire des fichiers seul car le seul but de sed est d'agir en tant qu'éditeur sur le "flux" (c'est-à-dire les pipelines de stdin, stdout, stderr et d'autres>&n
tampons, sockets et similaires). Dans cet esprit, vous pouvez utiliser une autre commandetee
pour réécrire la sortie dans le fichier. Une autre option consiste à créer un patch à partir de la canalisation du contenudiff
.Méthode des tés
Méthode de patch
METTRE À JOUR:
Notez également que le correctif entraînera la modification du fichier à partir de la ligne 1 de la sortie diff:
Le patch n'a pas besoin de savoir à quel fichier accéder car il se trouve dans la première ligne de la sortie de diff:
la source
/dev/stdin 2014-03-15
, a répondu le 7 janvier - êtes-vous un voyageur dans le temps?/dev/stdin
n'existe pas, vous devez donc remplacer/dev/stdin
par '-', un seul trait d'union sans les guillemets, donc les commandes suivantes devraient fonctionner:$ sed 's/oo/u/' fubar | diff -p fubar -
et$ sed 's/oo/u/' fubar | diff -p fubar - | patch
patch
cela ne sera pas tronqué aussi. Je pense que l'enregistrement de la sortie dans un autre fichier, puis lacat
saisie dans l'original serait plus sûr.Il n'est pas possible de faire ce que vous voulez
sed
. Même les versionssed
qui prennent en charge l'-i
option de modification d'un fichier sur place font exactement ce que vous avez explicitement déclaré que vous ne voulez pas: elles écrivent dans un fichier temporaire puis renomment le fichier. Mais vous pouvez peut-être simplement utilisered
. Par exemple, pour changer toutes les occurrences defoo
enbar
dans le fichierfile.txt
, vous pouvez faire:La syntaxe est similaire
sed
, mais certainement pas exactement la même.Mais vous devriez peut-être vous demander pourquoi vous ne voulez pas utiliser un fichier temporaire renommé. Même si vous n'avez pas de
-i
supportsed
, vous pouvez facilement écrire un script pour faire le travail pour vous. Au lieu de celased -i 's/foo/bar/g' file
, vous pourriez le faireinline file sed 's/foo/bar/g'
. Un tel script est trivial à écrire. Par exemple:devrait convenir à la plupart des utilisations.
la source
inline
et l'invoquerais comme décrit ci-dessus:inline inputfile sed 's/foo/bar/g'
ed
seule réponse qui fait vraiment sur place. C'est la première fois que j'en ai besoined
. Je vous remercie. Une petite optimisation consiste à utiliserecho -e ",s/foo/bar/g\012 w"
ouecho $',s/foo/bar/g\012 w'
lorsque le shell lui permet d'éviter untr
appel supplémentaire .ed
ne fait pas vraiment les modifications sur place. À partir de lastrace
sortie, GNUed
crée un fichier temporaire, écrit les modifications dans le fichier temporaire, puis réécrit l'intégralité du fichier d'origine, en préservant les liens durs. À partir de latruss
sortie, Solaris 11ed
utilise également un fichier temporaire, mais renomme le fichier temporaire en nom de fichier d'origine lors de l'enregistrement avec law
commande, détruisant tous les liens matériels.ed
qui est livré avec les macos actuelles (Mojave, quel que soit le jargon marketing) conserve toujours les liens physiques. YMMVVous pouvez utiliser vi
la source
sed prend en charge l'édition sur place. De
man sed
:Exemple :
Disons que vous avez un fichier
hello.txt
avec le texte:Si vous souhaitez conserver une sauvegarde de l'ancien fichier, utilisez:
Vous vous retrouverez avec deux fichiers:
hello.txt
avec le contenu:et
hello.txt.bak
avec l'ancien contenu.Si vous ne souhaitez pas conserver de copie, ne passez pas le paramètre d'extension.
la source
Vous n'avez pas spécifié quel shell vous utilisez, mais avec zsh vous pouvez utiliser la
=( )
construction pour y parvenir. Quelque chose dans le sens de:=( )
est similaire à>( )
mais crée un fichier temporaire qui est automatiquement supprimé à lacp
fin.la source
Devrait conserver tous les liens physiques, car la sortie est redirigée pour écraser le contenu du fichier d'origine, et évite d'avoir besoin d'une version spéciale de sed.
la source
Si vous remplacez le même nombre de caractères et après avoir lu attentivement l' édition «sur place» des fichiers ...
Vous pouvez également utiliser l'opérateur de redirection
<>
pour ouvrir le fichier en lecture et en écriture:Voir en direct:
Depuis le manuel de référence de Bash → 3.6.10 Ouverture de descripteurs de fichiers pour la lecture et l'écriture :
la source
Comme Moneypenny l'a dit dans Skyfall: "Parfois, les anciennes méthodes sont les meilleures." Kincade a dit quelque chose de similaire plus tard.
Bonne retouche en place. Ajout de \ nw \ n pour écrire le fichier. Toutes mes excuses pour la réponse tardive à la demande.
la source
|
. @MattMontag\n
. [range] s / <old> / <new> / <flag> est la forme de la commande de substitution - un paradigme encore présent dans de nombreux autres éditeurs de texte (okay, vim, un descendant direct de ed) Quoi qu'il en soit, leg
drapeau signifie "global", et signifie "chaque instance sur chaque ligne que vous regardez". La plage3,5
examine les lignes 3-5.,5
examine StartOfFile-5,3,
examine les lignes 3-EndOfFile et,
examine StartOfFile-EndOfFile. Une commande de substitution globale sur chaque ligne qui remplace "false" par "true". Ensuite, la commande d'écriture,,w
est entrée.De très bons exemples. J'ai eu le défi de modifier sur place de nombreux fichiers et l'option -i semble être la seule solution raisonnable à l'utiliser dans la commande find. Voici le script pour ajouter "version:" devant la première ligne de chaque fichier:
la source