0
votes

Remplacement des caractères dans chaque ligne sur un fichier sous Linux

J'ai un fichier avec un mot différent dans chaque ligne. Mon objectif est de remplacer le premier caractère à une lettre majuscule et de remplacer le 3ème caractère à "#".

Par exemple: le football sera échangé vers -> FOO # Ball

J'ai essayé de penser à utiliser awk et sed.it ne m'a pas aidé depuis (à ma connaissance) SED a besoin d'une entrée exacte du caractère et de l'AWK peut imprimer le caractère souhaité mais ne le modifie pas.


2 commentaires

Il est difficile de dire ce qui ne va pas avec votre code parce que vous ne l'avez pas fourni ni les erreurs que vous avez rencontrées. Voir également Comment créer un exemple minimal, complet et vérifiable .


SED a besoin d'une entrée exacte du caractère ? Complètement le contraire, SED ne peut pas fonctionner sur une entrée exacte du personnage - voir Stackoverflow.com/q/29613304/1745001 pour les cerceaux Vous devez sauter pour que SED agisse comme s'il utilisait des chaînes littérales.


7 Réponses :


4
votes

avec GNU SED et deux s code> s code> s: xxx pré>

sortie: p>

Foo#ball


0 commentaires

1
votes

Les réponses de Cyrus 'ou Potong sont les préférées. (Pour Linux ou Systèmes avec GNU SED à cause de \ u ou \ u.)

Il s'agit simplement d'une solution supplémentaire avec AWK car vous l'avez mentionnée et utilisée aussi AWK Tag: P>

$ echo 'football'|awk '{a=substr($0,1,1);b=substr($0,2,2);c=substr($0,5);print toupper(a)b"#"c}'
Foo#ball


2 commentaires

Laissez-moi l'appeller différemment :-): afaik je n'utilise aucune "extension GNU". Ainsi, la solution doit être la plus compatible.


Merci. Tout d'abord, je n'étais pas sûr de la compatibilité et de la seconde que je n'étais pas sûre de la langue (anglais). :-) Mise à jour.



0
votes

Ceci devrait fonctionner avec n'importe quelle version de awk : xxx

Remarque: Si un mot est inférieur à 3 caractères, comme , il sera imprimé sous le nom #


2 commentaires

"Parole différent dans chaque ligne": cela signifie qu'un seul mot est utilisé par ligne. Votre solution fonctionne également sur plusieurs mots d'une ligne.


Vrai. Eh bien, cela fonctionne également s'il n'y a qu'un seul mot dans chaque ligne. :)



2
votes

Avec BASH, vous pouvez utiliser uniquement les expansions de paramètres pour accomplir la tâche. Par exemple, si vous lisez chaque ligne dans la variable ligne code>, vous pouvez faire: xxx pré>

exemple de fichier d'entrée fort> p> p> XXX PRE>

EXEMPLE EXEMPLE UTILISATION / SORTIE STROND> P>

$ while read -r line; do line="${line^}"; echo "${line:0:3}#${line:4}"; done < file
Foo#ball
Soc#er
Bas#ball


4 commentaires

Le Lire seul le rendra extrêmement lent par rapport à une solution SED ou AWK, voir Unix.stackexchange. COM / Q / 169716/133219 . Toujours citer vos variables sauf si vous besoin pour faire quelque chose que nécessite qu'ils doivent être inclus - voir mywiki.woolgedge.org/quotes . Dans ce cas, même si nous supposons qu'il n'y a pas d'espaces dans l'entrée, vous obtiendrez des résultats malheureux si l'entrée contenait des caractères de globe qui vient de correspondre à des noms de fichiers locaux.


Oui, cela ne fait que environ 100 000 lignes par seconde (avec SSD), donc si votre fichier est des millions, vous voudrez quelque chose de plus rapidement. Si vous avez affaire à 1000 lignes ou moins, c'est dans le bruit. D'accord sur la citation, cela venait d'omettre en raison de l'entrée d'un mot - mais cela devrait être là pour la généralisation.


Sur ma machine, il faut 4,81 secondes pour 100 000 lignes :-). La solution GNU SED de GNU de FWIW Potong (sans surprise, car c'est ce que SED est le meilleur pour) a pris 0,17 seconde tandis que mon GNU awk one a pris 0,98 sec et Reichharts Posix Awk a pris seulement 0,22 sec. D'accord sur le "Si vous traitez avec 1000 lignes ou moins ..." Mais vous chercheriez ensuite une autre raison de l'utiliser sur SED ou Awk. Je n'ai que commentaire seulement parce que vous avez dit lorsque l'utilisation est limitée aux produits, il ne tombe pas trop loin derrière car il tombe toujours très loin derrière.


J'ai utilisé / usr / lib / dict / mots pour le test 305089-mots ( 3.481s total). Je ne dis pas que c'est plus rapide, vous le savez. Le "pas trop loin derrière" pourrait mieux être exprimé comme "pas aussi mauvais que d'appeler un utilitaire supplémentaire à l'intérieur de la boucle" . awk solution (1,833s Total) Même fichier, exécuté dans SUBSHELL redirigé vers / dev / null .



2
votes

Cela pourrait fonctionner pour vous (GNU SED):

sed 's/\(...\)./\u\1#/' file


0 commentaires

1
votes

avec GNU AWK pour le 3ème Arg pour correspondre ():

$ echo 'football' | awk 'match($0,/(.)(..).(.*)/,a){$0=toupper(a[1]) a[2] "#" a[3]} 1'
Foo#ball


1 commentaires

Merci. Dans ce cas, il est un peu trop exclu que si cela est vraiment tout ce qui doit être fait, je devrais aller avec @potongs Si vous avez des outils GNU et si vous n'êtes pas alors @reichharts .



0
votes

Si vos données dans le fichier 'D', essayé sur GNU SED:

sed -E 's/^(\w)(\w\w)\w/\U\1\E\2#/' d


0 commentaires