3
votes

Remplacez les espaces uniquement après une correspondance dans sed ou awk

Il y a cet ensemble de lignes que j'aurais besoin de modifier

00:00  07:45 01._Alva
07:45  14:40 02._Whit_Cliffs
14:40  20:22 03._Ribcag_#1 
20:22  25:04 04.__a_Oidipus

Après une correspondance (qui pourrait être le point), j'aurais besoin de remplacer les espaces qui suivent, (et seulement ceux qui suivent ) avec des tirets - ou des traits de soulignement _ .

Résultat attendu:

sed -i 's/\(\.\)\(\s*\)/\1_/g' dummyfile2 | sed -i 's/\([[:alpha:]][[:space:]]\)\(\s*\)/_/g' dummyfile2

J'ai déjà essayé ce qui suit avec des résultats mitigés ...

dummyfile2 est le nom du fichier que j'utilise pour stocker les chaînes de texte

00:00  07:45 01._Alva
07:45  14:40 02._WhiteCliffs
14:40  20:22 03._Ribcage #1 
20:22  25:04 04._I am Oidipus

donne le résultat:

sed -i 's/\(\.\)\(\s*\)/\1_/' dummyfile2 | sed -i 's/\(_\)\(\s*\)/\1_/' dummyfile2

J'ai aussi essayé de faire ce qui suit ...

00:00  07:45  01._Alva 
07:45  14:40  02._White_Cliffs 
14:40  20:22  03._Ribcage_#1 
20:22  25:04  04._I_am_Oidipus

donne le résultat:

00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04. I am Oidipus

Ce dernier était le le plus proche que j'ai pu trouver. (Mais ce n'est pas le résultat attendu.)


2 commentaires

Veuillez consulter: Que dois-je faire lorsque quelqu'un répond à ma question?


Merci pour les conseils Tiw! J'y réfléchirai la prochaine fois que je posterai une question pour que je puisse la rendre plus facile à comprendre. À votre santé.


9 Réponses :


2
votes

EDIT: Il semble que les autres solutions ne prennent en charge que l'espace en substituant le tout premier espace après . ce qui suit prendra soin de tous les espaces.

pre> XXX



Si vous essayez dans sed , alors ce qui suit peut vous aider. Vous n'avez pas besoin d'utiliser plusieurs commandes sed .

awk '{sub(/\. +/,"._")} 1' Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus

Modifiez sed -E's / \. + / \ ._ / ' TO sed -E' s / \. + / \ ._ / g ' ci-dessus au cas où vous auriez plusieurs occurrences de . (espaces) dans une ligne.



Si vous êtes d'accord avec awk alors pourriez-vous essayer de suivre.

cat Input_file
00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04.   I am Oidipus

Si vous avez plusieurs occurrences de . alors remplacez sub avec gsub dans la commande ci-dessus. La sortie sera la suivante.

00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus

Code testé ci-dessus avec plusieurs espaces: Disons que nous avons plusieurs espaces après . alors aussi le code aboe fonctionnera. En supposant que votre fichier_entrée est comme suit.

awk '{sub(/\. +/,"._")} 1' Input_file

Ici, j'ai changé la dernière ligne en ajoutant plus d'espaces après . , maintenant après l'exécution du code, il les remplacera avec un seul _ comme suit.

sed -E 's/\. +/\._/'  Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus


0 commentaires

3
votes

awk à la rescousse!

$ awk 'BEGIN{FS=OFS="."} {gsub(/ /,"_",$2)}1' file

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus


1 commentaires

Cela échouerait si le texte après le premier . contenait également des . s et cela ressemble à du texte libre pour moi, donc je ne vois aucune raison de penser qu'il ne pourrait pas ' t contiennent . s.



0
votes

Avec GNU sed, vous pouvez le faire comme ceci:

sed -e ':a' -e 's/\(\.[^[:space:]]*\)[[:space:]][[:space:]]*\([^[:space:]][^[:space:]]*\)/\1_\2/;' -e 'ta' file

Exemple (ajout d'un cas de bord):

$ cat file
00:00  07:45  01. Alva
07:45  14:40  02. White Cliffs
14:40  20:22  03. Ribcage #1
20:22  25:04  04. I am Oidipus
20:22  25:04  05.U re  spe   cial

$ sed -E ':a;s/(\.\S*)\s+(\S+)/\1_\2/;ta' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
20:22  25:04  05.U_re_spe_cial

POSIX sed conforme:

sed -E ':a;s/(\.\S*)\s+(\S+)/\1_\2/;ta'

Si vous êtes sûr qu'il n'y a pas d'espaces de fin dans vos lignes ou que vous voulez que les espaces de fin soient également remplacés, vous pouvez supprimer le deuxième groupe de capture ( ( ...) ou \ (... \) ) et le \2.


4 commentaires

Vous n'avez pas besoin d'une deuxième référence arrière. Même sortie avec sed -E ': a; s / (\. \ S *) / \ 1 _ /; ta' file .


@SLePort Il y a des espaces de queue dans les exemples de données d'OP, et évidemment OP ne veut pas que les espaces de queue soient remplacés par un trait de soulignement. Nous pouvons également interpréter l'intention de OP par le code (\ s * \) à _ que OP veut remplacer plusieurs espaces consécutifs par un seul _ .


Il n'y a rien d'évident sur la façon dont OP veut gérer les espaces de fin. Et ce sont des exemples de données, pas un fichier source. Les espaces de fin peuvent être le résultat d'un copier-coller.


@SLePort C&P ne causera pas cela, il pourrait s'agir d'une erreur de formatage d'OP lors de la publication de la question. Quoi qu'il en soit, c'est le moyen le plus sûr de le faire.



0
votes

Avec n'importe quel awk dans n'importe quel shell sur n'importe quelle boîte UNIX:

$ awk 'match($0,/([^.]+.)(.*)/,a){$0=a[1] gensub(/ /,"_","g",a[2])} 1' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
20:22  25:04  05._here_is_a_dot._that_may_hurt._idk.

ou avec GNU awk pour le 3ème argument à match () et gensub ():

$ awk 'p=index($0,"."){tl=substr($0,p+1); gsub(/ /,"_",tl); $0=substr($0,1,p) tl} 1' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus


0 commentaires

0
votes

Avec sed (compatible POSIX):

sed -e :a -e 's/\(\.[^ ]*\)  */\1_/;ta' file

Si vous souhaitez remplacer les espaces consécutifs par un seul _ :

sed -e :a -e 's/\(\.[^ ]*\) /\1_/;ta' file


0 commentaires

0
votes

Avec la modification de texte procédurale, vous pouvez y parvenir comme ceci:

forEach line {
  select (after ci ".") { findReplace ci " " "_" }
}


0 commentaires

2
votes

Cela pourrait fonctionner pour vous (GNU sed):

sed -E 's/\s+\</_/3g' file

Remplacez le troisième groupe d'espaces avant un mot et au-delà par un _ . p >


0 commentaires

0
votes

Beaucoup de bonnes réponses. Je suis nouveau sur awk mais voici une solution simple

{print $0}

Voici mon InputFile

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus


0 commentaires

1
votes

Utilisation de Perl

$ perl -pe ' s/(?:\S+)\. (.+)$/$x=$&;$x=~s! !_!g;$x/ge ' whitespace.txt
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus

$


2 commentaires

Plus simple: perl -pe's / \. \ K (. +) $ / $ 1 = ~ s {\ s +} {_} gr / ge 'whitespace.txt


(Commence à remplacer après le premier . . Pour passer du dernier, s /.* \. \ K ... / )