La question indique explicitement que les titres contiendront des espaces. Pour des raisons de sécurité, je suppose que les titres peuvent contenir des points ; par exemple, "L'histoire de 3.14159" ou "La découverte du Dr. Doolittle". Mes réponses supposent qu'il y a algunos caractère qui n'apparaîtra jamais dans la table des matières ; Plus précisément, ils supposent que c'est @
. Si vous avez @
dans votre table, remplacez-le par un caractère qui n'apparaît jamais (par exemple #
, ^
, _
, |
etc.). Si vous utilisez vraiment tous les caractères ASCII, il vous faudra peut-être utiliser une séquence de caractères, telle que <@>
.
Trois façons de le faire avec sed
:
Boucle :
sed 's/\(.*\)\( \)/\1@\2/; :loop; s/ @/ @./; t loop; s/@//'
-
s/\(.*\)\( \)/\1@\2/
trouve le dernier espace sur la ligne et insère un @
avant elle.
-
:loop
est une étiquette, comme une borne kilométrique.
-
s/ @/ @./
(c'est s/@/@./
pour éviter toute ambiguïté) dit, s'il y a deux espaces avant le @
, remplacez-les par .
(espace et point), et déplacez le @
entre eux.
-
t loop
dit, si la substitution ci-dessus a réussi, revenir à la :loop
marqueur et répétez. Sinon, continuez à
-
s/@//
qui supprime le @
.
Ainsi, le foo bar
dans votre tableau seront traitées comme suit :
Initial value: foo bar url3
s/\\(.\*\\)\\( \\)/\\1@\\2/ foo bar @ url3
s/ @/ @./ foo bar @. url3
s/ @/ @./ foo bar @.. url3
s/ @/ @./ foo bar @.. url3 _(Substitution fails, so don’t loop)_
s/@// foo bar .. url3
Final output: foo bar .. url3
Des chiffres écrasants :
sed 's/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/; s/ [ @]\{20\}/ /; s/@/./g'
-
s/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/
est très similaire à la première s
dans la première solution ; elle trouve le dernier espace sur la ligne et insère une chaîne de 20 @
les caractères qui le précèdent. Cela devrait être un nombre qui est au moins aussi grand que le nombre maximum de points que vous devrez jamais insérer sur une ligne, par exemple 80. Gérer une chaîne de 80 @
les personnages seraient gênants ; vous pourriez le remplacer par
-
s/\(.*\)\( \)/\1<@><@><@><@><@>\2/; s/<@>/@@@@@@@@/g
qui insère une chaîne de cinq <@>
séquences, et remplace ensuite chacune d'entre elles par une chaîne de 16 @
des personnages, ce qui donne 5×16=80 @
des personnages.
-
s/ [ @]\{20\}/ /
trouve une chaîne de 20 caractères consécutifs qui sont soit un espace, soit un @
précédé d'un espace, et le remplace par le seul espace précédent. Remplacer 20
avec le numéro de l'étape précédente.
-
s/@/./g
remplace chaque @
avec un point.
Ainsi, le foo
dans votre tableau seront traitées comme suit :
Initial value: foo url1
s/\(.*\)\( \)/\1@@@@...@@@@\2/ foo @@@@@@@@@@@@@@@@@@@@ url1
s/ [ @]\{20\}/ / _[remove]
foo @@@@@@ url1
s/@/./g foo ...... url1
Utilisez l'"espace de maintien" :
sed 's/.*[^ ] /&@/; h; s/ /./g; s/\(\.*\)\./\1 /; x; G; s/@.*@//'
-
s/.*[^ ] /&@/
es similaire aux commandes précédentes ; il trouve la fin du titre - pour être précis, le dernier endroit où un caractère non-blanc est suivi d'un espace - et insère un @
après elle.
-
h
copie la ligne dans l'espace d'attente.
-
s/ /./g
remplace tous les espaces de la ligne par des points.
-
s/\(\.*\)\./\1 /
remplace le dernier point par un espace. (Cela devra changer si l'URL peut contenir des points, ce qui, je suppose, est probable).
-
x
échange l'espace du motif et l'espace du maintien.
-
G
ajoute l'espace de maintien à l'espace du motif. Nous avons maintenant, essentiellement, deux copies de la ligne.
-
s/@.*@//
conserve la première partie de la première copie et la seconde partie de la seconde copie, en se débarrassant de ce qui se trouve au milieu.
Initial value: foo bar url3
Pattern space Hold space
s/.[^ ] /&@/ foo bar @ url3
h foo bar @ url3 foo bar @ url3
s/ /./g foo.bar.@...url3 foo bar @ url3
s/(.)./\1 / foo.bar.@.. url3 foo bar @ url3
x foo bar @ url3 foo.bar.@.. url3
G foo bar @ url3 foo.bar.@.. url3 foo.bar.@.. url3
s/@.*@// foo bar .. url3 foo.bar.@.. url3
Final output: foo bar .. url3