J'ai une très longue chaîne, avec plus de 2000 occurrences, et ça ressemble à ça:

Contribution:

1a2a3a4a5a6a7a8absoad8ryaa90thneas ... et plus que

Je veux remplacer plusieurs occurrences de la 3e à la 450e occurrence dans la chaîne pour afficher:

1a2a3A4A5A6A7A8AbsoAd8ryAA90thneAs ... et plus que

J'ai remplacé "a" par "A", il a remplacé de la 3ème occurrence à la fin, mais je veux seulement remplacer de la 3ème à la 450ème, ceci est mon ancien script:

echo "1a2a3a4a5a6a7a8absoad8ryaa90thneas..." | sed 's/a/A/3g';

Quelqu'un m'aide-t-il? Ou y a-t-il un autre moyen? Merci!

2
Merson Su 18 nov. 2017 à 13:31

4 réponses

Meilleure réponse

Choisissez un caractère dont vous savez avec certitude qu'il n'est pas présent dans votre entrée .. par exemple le caractère ASCII NUL, alors vous pouvez faire

$ # replacing 3rd to 4th
$ echo "a1a23a5a62a34a235a" | sed 's/a/\x0/3g; s/\x0/a/3g; s/\x0/A/g'
a1a23A5A62a34a235a
$ # replacing 3rd to 5th
$ echo "a1a23a5a62a34a235a" | sed 's/a/\x0/3g; s/\x0/a/4g; s/\x0/A/g'
a1a23A5A62A34a235a
$ # replacing 3rd to 6th
$ echo "a1a23a5a62a34a235a" | sed 's/a/\x0/3g; s/\x0/a/5g; s/\x0/A/g'
a1a23A5A62A34A235a
0
Sundeep 18 nov. 2017 à 11:20

Enregistrez la chaîne dans une variable, puis utilisez le développement d'accolades pour cibler le caractère de position dans la chaîne que vous souhaitez remplacer à l'aide de bash global replace. Prenons l'exemple suivant:

## Our sample string. ##
string="abcde01234

## New, changed string. ##
echo "${string//${string:0:1}/${string:5:1}}"

Dans cet exemple, lorsqu'il est exécuté en tant que script bash, le premier caractère de $string est remplacé par le sixième caractère de $string. Connaissant cette petite astuce, je suis sûr que vous trouverez un moyen de faire ce dont vous avez besoin sans avoir à utiliser sed. Ou, vous pouvez utiliser le développement d'accolades de la même manière dans sed.

## Our sample string ##
string="abcde01234"

## New, changed, string. Output is the same as above example. ##
sed -e "s/${string:0:1}/${string:5:1}/g" <(echo "$string")

Cela devrait être suffisant pour vous orienter dans la bonne direction en ce qui concerne la meilleure façon de répondre à vos besoins.

1
Yokai 18 nov. 2017 à 11:37

Cela pourrait fonctionner pour vous (GNU sed):

sed -r 's/a/\n&/3;s//&\n/450;h;y/a/A/;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/' file

Divisez la chaîne en morceaux à l'aide d'un marqueur (le retour à la ligne ne peut pas se produire dans une chaîne pure, car c'est ainsi que sed divise les fichiers), faites une copie, puis apportez des modifications, ajoutez la copie et réorganisez les morceaux.

Vous pouvez également utiliser l'indicateur de remplacement global GNU sed:

sed 's/a/\n/451g;s//A/3g;s/\n/a/g' file
0
potong 19 nov. 2017 à 09:53

sed -E ':again ; s/^(.{4,449})a/\1A/ ; t again' file

Vous pouvez utiliser la commande t pour branchez à libellé. Il s'agit d'un aller à :label conditionnel lorsqu'un remplacement a eu lieu. Donc, pour une plage de caractères [x:y], l'expression régulière .*{x-1,y-1}a correspondra à gourmand pour la première fois, mais nous bouclons jusqu'à ce qu'il n'y ait plus de correspondances.

0
thanasisp 19 nov. 2017 à 10:18
47365032