web-dev-qa-db-fra.com

Remplacement en place

J'ai un CSV. Je veux éditer le 35ème champ du CSV et écrire la modification dans le 35ème champ. Voici ce que je fais sur Bash:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g'

donc, je tire la 35ème entrée en utilisant awk puis je remplace le "0" dans la position de départ dans la chaîne par "+91". Celui-ci fonctionne parfaitement et je reçois la sortie désirée sur la console. 

Maintenant, je veux que cette nouvelle entrée soit écrite dans le fichier. Je pense à la fonctionnalité de remplacement "in-situ" de sed, mais ce fetuare a besoin d’un fichier d’entrée. Dans la commande ci-dessus, je ne peux pas fournir de fichier d'entrée car ma commande principale est awk et sed prend l'entrée de awk.

Merci.

25
slayedbylucifer

Vous devriez choisir l'un des deux outils. En ce qui concerne sed, cela peut être fait comme suit:

sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/' test.csv 

Pas sûr de awk, mais le commentaire de @ shellter pourrait aider à cela.

46
Lev Levitsky

La fonctionnalité in-place de sed est mal nommée, car elle ne modifie pas le fichier en place. Au lieu de cela, il crée un nouveau fichier portant le même nom. par exemple:

$ echo foo > foo
$ ln -f foo bar
$ ls -i foo bar  # These are the same file
797325 bar  797325 foo
$ echo new-text > foo  # Changes bar
$ cat bar
new-text
$ printf '/new/s//newer\nw\nq\n' | ed foo  # Edit foo "in-place"; changes bar
9
newer-text
11
$ cat bar
newer-text
$ ls -i foo bar  # Still the same file
797325 bar  797325 foo
$ sed -i s/new/newer/ foo   # Does not edit in-place; creates a new file
$ ls -i foo bar
797325 bar  792722 foo    

Puisque sed n’édite pas réellement le fichier sur place, mais écrit un nouveau fichier puis le renomme en ancien fichier, vous pouvez également en faire de même. 

awk ... test.csv | sed ... > test.csv.1 && mv test.csv.1 test.csv

Il existe une idée fausse selon laquelle l'utilisation de sed -i évite en quelque sorte la création du fichier temporaire. Ce ne est pas. Il cache juste le fait de vous. Parfois, l'abstraction est une bonne chose, mais d'autres fois, il s'agit d'un obscurcissement inutile. Dans le cas de sed -i, c'est ce dernier. Le shell est vraiment bon pour la manipulation de fichiers. Utilisez-le comme prévu. Si vous avez besoin de modifier un fichier sur place, n'utilisez pas la version en continu de ed; utilisez simplement ed

16
William Pursell

Cela pourrait fonctionner pour vous:

sed -i 's/[^,]*/+91/35' test.csv

MODIFIER:

Pour remplacer le zéro initial dans le 35ème champ:

sed 'h;s/[^,]*/\n&/35;/\n0/!{x;b};s//+91/' test.csv

ou plus simplement:

|sed 's/^\(\([^,]*,\)\{34\}\)0/\1+91/' test.csv
2
potong

Si vous avez moreutils installé, vous pouvez simplement utiliser l'outil sponge:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g' | sponge test.csv

sponge absorbe l'entrée, ferme le canal d'entrée (stdin), puis seulement ouvre et écrit dans le fichier test.csv.

À partir de 2015, moreutils est disponible dans les dépôts de paquets de plusieurs distributions Linux majeures, telles que Arch Linux , Debian et Ubuntu .

0
Rudy Matela

Une autre solution Perl pour modifier le 35ème champ sur place:

Perl -i -F, -lane '$F[34] =~ s/^0/+91/; print join ",",@F' test.csv

Ces options de ligne de commande sont utilisées: 

  • -i édite le fichier sur place 
  • -n boucle autour de chaque ligne du fichier d'entrée 
  • -l supprime les nouvelles lignes avant traitement et les rajoute après 
  • -a mode autosplit - divise les lignes d’entrée dans le tableau @F. La valeur par défaut est la division sur les espaces blancs. 
  • -e exécuter le code Perl 
  • -F modificateur autosplit, dans ce cas, scinde le , 

@F est le tableau de mots de chaque ligne, indexé à partir de 0
$F[34] est l'élément 35 du tableau
s/^0/+91/ fait la substitution

0
Chris Koknat