web-dev-qa-db-fra.com

Utilisez sed pour utiliser "rechercher et remplacer" à chaque deuxième occurrence.

J'ai un dossier avec +1000 fichiers .dat. Et chaque fichier contient plusieurs lignes du type suivant:

-0.0999999999999659-0.0000000006287859
-0.08999999999997500.8000000006183942
-0.0799999999999841-0.0000000007463807
-0.06999999999999320.0000000008661516
-0.06000000000000230.0000000008640644
-0.05000000000001140.0000000008807621
-0.0400000000000205-0.7000000009575896
-0.02999999999997270.0000000009476864
-0.01999999999998180.0000000009150902
-0.00999999999999090.0000000008144152
0.00000000000000000.0000000007097434
0.00999999999999090.0000000007847500
0.01999999999998180.0000000009030998
0.03000000000002960.0000000009741985

Pour tous les fichiers que je veux convertir en

-0.0999999999999659    -0.0000000006287859
-0.0899999999999750    0.8000000006183942
-0.0799999999999841    -0.0000000007463807
-0.0699999999999932    0.0000000008661516
-0.0600000000000023    0.0000000008640644
-0.0500000000000114    0.0000000008807621
-0.0400000000000205    -0.7000000009575896
-0.0299999999999727    0.0000000009476864
-0.0199999999999818    0.0000000009150902
-0.0099999999999909    0.0000000008144152
0.0000000000000000    0.0000000007097434
0.0099999999999909    0.0000000007847500
0.0199999999999818    0.0000000009030998
0.0300000000000296    0.0000000009741985

La seule chose qui soit cohérente dans tous ces fichiers est que le deuxième nombre (correspondant au deuxième point de chaque ligne) est toujours inférieur à 1,0 et supérieur à -1,0. Mais le premier nombre peut prendre n'importe quelle valeur réelle.

J'ai donc pensé à utiliser "trouver et remplacer" niquement pour le deuxième "point" comme suit. Trouver:

0.

Remplacer par:

   0.

Je ne sais pas comment spécifier sed uniquement pour agir sur le "deuxième point" de chaque ligne. Est-ce que quelqu'un a une bonne idée sur la façon de faire cela?

4
Hunter
 sed -E s'/(.*[^-])(-?0\.)/\1    \2/' 999.dat

Le * est gourmand et mange le plus de caractères possible afin que le \. corresponde toujours au dernier de la ligne. Le [^-] garantit que le - facultatif du deuxième numéro entre dans le deuxième groupe.

5
Florian Diesch

Pour ne remplacer que la deuxième occurrence, utilisez le modificateur 2. Ainsi:

$ sed -E 's/-?[[:digit:]][.]/    &/2' file.dat
-0.0999999999999659    -0.0000000006287859
-0.0899999999999750    0.8000000006183942
-0.0799999999999841    -0.0000000007463807
-0.0699999999999932    0.0000000008661516
-0.0600000000000023    0.0000000008640644
-0.0500000000000114    0.0000000008807621
-0.0400000000000205    -0.7000000009575896
-0.0299999999999727    0.0000000009476864
-0.0199999999999818    0.0000000009150902
-0.0099999999999909    0.0000000008144152
0.0000000000000000    0.0000000007097434
0.0099999999999909    0.0000000007847500
0.0199999999999818    0.0000000009030998
0.0300000000000296    0.0000000009741985

Comment ça fonctionne:

  • -E

    Cela indique à sed d'utiliser une expression rationnelle étendue. Ceci élimine le besoin d'échapper au ?.

  • s/-?[[:digit:]][.]/ &/2

    Ceci recherche un - facultatif suivi d'un chiffre suivi d'un littéral .. Dans le texte de remplacement, quatre espaces sont ajoutés avant la chaîne correspondante, notée &.

    Le modificateur 2 situé à la fin de la commande de substitution indique à sed de ne remplacer que la deuxième occurrence du motif.

Exemples connexes

Quelques exemples supplémentaires montrant comment différentes substitutions peuvent être effectuées:

$ echo aaaa | sed 's/a/A/1'
Aaaa
$ echo aaaa | sed 's/a/A/2'
aAaa
$ echo aaaa | sed 's/a/A/3'
aaAa
$ echo aaaa | sed 's/a/A/4'
aaaA
$ echo aaaa | sed 's/a/A/g'
AAAA
5
John1024

trouvez le premier point :)

sed -r 's/(.*\.[^-\.]*)(-?)0\.(.*)/\1\t\20.\3/' file

Remarques

  • -r utilise ERE
  • s/old/new remplace old par new
  • (some chars) enregistrer some chars pour faire référence ultérieurement
  • .* un nombre quelconque de caractères
  • \. littéral .
  • [^-\.] tous les caractères sauf le tiret ou .
  • -? facultatif -
  • \1\t\20.\3 imprimer les motifs sauvegardés, un onglet et 0. aux endroits appropriés
2
Zanna

Que diriez-vous

$ sed -E 's/(-?0\.[0-9]+)(-?0\.[0-9]+)/\1\t\2/' file
-0.0999999999999659     -0.0000000006287859
-0.0899999999999750     0.8000000006183942
-0.0799999999999841     -0.0000000007463807
-0.0699999999999932     0.0000000008661516
-0.0600000000000023     0.0000000008640644
-0.0500000000000114     0.0000000008807621
-0.0400000000000205     -0.7000000009575896
-0.0299999999999727     0.0000000009476864
-0.0199999999999818     0.0000000009150902
-0.0099999999999909     0.0000000008144152
0.0000000000000000      0.0000000007097434
0.0099999999999909      0.0000000007847500
0.0199999999999818      0.0000000009030998
0.0300000000000296      0.0000000009741985

Comment ça fonctionne:

  • -?0\.[0-9]+ correspond à 0. suivi d'un ou de plusieurs autres chiffres décimaux et éventuellement précédé de -
  • (-?0\.[0-9]+)(-?0\.[0-9]+) capture 2 instances de ce qui précède
  • \1\t\2 les remplacer par un TAB entre les deux
2
steeldriver