Si vous qualifiez un mot pour signifier n'importe quelle séquence de 1 ou plusieurs caractères non vides, la réponse est certainement oui, et cela se fait très simplement également. En effet, [[:blank:]]*
et [^[:blank:]]*
sont des compléments booléens et - à condition que tous les caractères d'une chaîne soient complets - [[:blank:]]*
U [^[:blank:]]*
peut décrire n'importe quelle chaîne possible de la même manière .*
.
Si un caractère incomplet ou une séquence d'octets non valide existe dans une chaîne, ni l'un ni l'autre ne peut le décrire correctement, comme cela peut parfois se produire lors de l'interprétation d'une chaîne dans le mauvais codage. Pour garantir un caractère complet par octet dans n'importe quelle chaîne, les paramètres régionaux C peuvent être forcés comme:
LC_ALL=C sed ...
... ce qui éviterait tout problème de description de la chaîne de la tête à la queue avec un modèle tout compris tel que .*
ou([ ]*[^ ]*)*
Un modèle entièrement complémentaire peut répéter autant de fois que nécessaire de gauche à droite la longueur de n'importe quelle chaîne pour atterrir sur la dernière occurrence possible sans interruption du modèle. C'est, définitivement, un langage régulier.
BRE:
sed 's/\(\([^[:blank:]]*\)[[:blank:]]*\)*/\2/'
AVANT:
sed -E 's/(([^[:blank:]]*)[[:blank:]]*)*/\2/'
Ces deux versions imprimeront toujours des lignes vierges, et c'est parce que l' *
étoile Kleene correspond à zéro ou plusieurs occurrences d'un motif. Il correspond d'abord à zéro ou plusieurs caractères non vides, puis à zéro ou plusieurs caractères vides, puis à zéro ou plusieurs occurrences des correspondances groupées jusqu'à ce qu'il corresponde à la chaîne dans son intégralité.
Ayant fait correspondre tout cela, la magie opère dans le remplacement - les références retournées par les groupes \1
et \2
sont les dernières occurrences de chacun. Ainsi, lorsque le remplacement est effectué, toute la chaîne est remplacée par la dernière occurrence sur une ligne de zéro ou plusieurs caractères non vides - ou le sous-groupe \2
.
Bien sûr, cela fonctionne pour toute chaîne possible - même une chaîne vide - ce qui signifie que les deux formulaires imprimeront des caractères de nouvelle ligne pour les lignes qui ne contiennent que des caractères vierges ou pas du tout. Pour gérer cela, vous pouvez faire quelques choses, mais rendons d'abord la classe de caractères un peu plus facile à taper:
b='[:blank:]'
Maintenant, pour imprimer uniquement si une ligne contient un ou plusieurs caractères non vides, vous pouvez faire:
BRE:
sed -n "s/\(\([^$b]*\)[$b]*\)*/\2/;/./p"
AVANT:
sed -En "/[^$b]/s/(([^$b]*)[$b]*)*/\2/p"
- Cas BRE - la substitution est toujours effectuée et seuls les espaces de motif avec au moins un caractère restant sont imprimés.
- Cas ERE - la substitution n'est tentée que sur un espace modèle contenant au moins un caractère non vide.
L'une ou l'autre forme fonctionnera avec l'une ou l'autre méthode - tant que la syntaxe est correcte.
Le -n
commutateur désactive l'impression automatique de l'espace de motif et l' p
indicateur de l' s///
ubstitution ou des commandes d' /
adresse /
imprime ses résultats uniquement en cas de succès.
Cette même logique peut également être appliquée pour obtenir n'importe quelle {num}
occurrence, comme:
BRE:
sed -n "s/\([$b]*\([^$b]\{1,\}\)\)\{num\}.*/\2/p"
AVANT:
sed -En "s/([$b]*([^$b]+)){num}.*/\2/p"
... où les num
deux expressions rationnelles peuvent être remplacées par un nombre pour imprimer uniquement l' {num}
occurrence spécifiée d'une séquence de caractères non vides. Une forme légèrement différente est utilisée ici pour garantir que le nombre n'est pas faussé pour l'espace de début dans une chaîne.
Notez que le -E
commutateur ERE sed
est pris en charge dans les versions BSD et GNU, bien qu'il ne soit pas encore la syntaxe standard POSIX.
sed
?